Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 重构决策:消息队列库、同步调用者或卸载在库中创建专用读/写线程_C++_Linux_Design Patterns_Boost_Client Side - Fatal编程技术网

C++ 重构决策:消息队列库、同步调用者或卸载在库中创建专用读/写线程

C++ 重构决策:消息队列库、同步调用者或卸载在库中创建专用读/写线程,c++,linux,design-patterns,boost,client-side,C++,Linux,Design Patterns,Boost,Client Side,我正在重构一个我没有设计的项目。它是用C/C++for linux编写的。该项目的主要客户端组件如下所示: 客户端->输出队列库(OQL)->控制器 客户 凌乱的半复杂代码,设计拙劣(使用单例/名称空间的OOP近似的大杂烩,在许多地方很奇怪-但它可以工作) 自定义协议实现(不是我的协议,无法修改) 共享库 多线程 多线程调用OQL api,即多线程输出 通过API接受来自控制器的命令 产生大量未排序的输出,该输出受控制器输入的影响,但不一定直接(绝对不是1:1) 输出队列库(OQL)

我正在重构一个我没有设计的项目。它是用C/C++for linux编写的。该项目的主要客户端组件如下所示:

客户端->输出队列库(OQL)->控制器

客户
  • 凌乱的半复杂代码,设计拙劣(使用单例/名称空间的OOP近似的大杂烩,在许多地方很奇怪-但它可以工作)
  • 自定义协议实现(不是我的协议,无法修改)
  • 共享库
  • 多线程
    • 多线程调用OQL api,即多线程输出
  • 通过API接受来自控制器的命令
  • 产生大量未排序的输出,该输出受控制器输入的影响,但不一定直接(绝对不是1:1)
输出队列库(OQL)
  • 简单干净的代码,并不是为当前的工作负载设计的(从来没有打算排队,实际上最初只是向stdout写入,然后一个消息队列被插入)
  • 共享库
  • 单螺纹
  • 公开API,该API接受来自客户端的多种类型的数据,并构建此数据的文本表示
  • 将数据插入sys V消息队列
控制器
  • 可执行
  • 单螺纹
  • 优雅、容错C++,广泛使用Booost
  • 这是我白手起家写的,可以说是我被允许完全“修复”的项目的唯一部分
  • 通过API与客户端库交互以启动到服务器的连接
    • 将客户机生成的数据和从OQL读取的数据保存到另一层的数据库中
所以问题本质上归结为这一点,控制器是单线程的,并且调用客户机库中的许多API函数。由控制器调用客户端API产生的场景

  • 正常(98%+)
  • 控制器调用客户端API函数
  • 客户端API函数在内部执行魔术
  • API函数返回true
  • 客户机在另一个执行线程中接收第2步魔术的结果数据,并从辅助线程调用OQL put函数
  • OQL将数据写入消息队列,队列阻塞或不阻塞都不重要,因为控制器的主执行线程正在运行和处理数据
  • 成功
  • 问题情景
  • 控制器调用客户端API函数
  • 客户端API函数立即生成结果,然后从控制器中执行的主线程返回调用OQL put函数
  • OQL将数据写入消息队列,出现以下情况之一:
  • 消息队列未满,不阻塞,所有内容都返回,控制器处理消息队列中的新数据,生活愉快地继续
  • 问题场景消息队列已满,无法阻止
  • 现在我确信您可以看到的是问题场景,这是罕见的,执行的主线程阻塞在完整的消息队列上,并且队列的另一端没有处理任何数据,因为控制器是单线程的

    是的,这有点混乱,不,我对设计不满意,但我必须找出解决这个问题的最佳方法,而不必重写所有这些交互

    我正试图在以下两者之间做出选择:

  • 深入客户机,将所有线程同步到与OQL交互的单个I/O线程

    • 我基本上不相信,在我之后的人不会进来破坏这条路,引入大量的bug,并且无法理解为什么
  • 在OQL中引入writer线程

    • 接受一个简单的类,并使其显著复杂化
    • 介绍有趣的问题
      • 队列在该点不需要队列吗?因为数据必须传输到写入线程

  • 事实上,仅仅输入这个问题可能是我能做的最好的事情,因为我的想法现在更有条理了……但是有人能提供任何意见吗?是否有一些设计模式我没有看到,这将不需要大规模重构,我的担心是否夸大了这些?我甚至不确定是否有人可以在不了解问题所有角度的情况下提供有意义的建议,但我很感激你们能提供的任何见解。

    更改客户端以在Q满时返回错误,这样控制器就可以智能地决定如何继续。

    您可以将控制器更改为使用第二个线程从消息队列读取(只需将数据发布到控制器内部一个更大的缓冲区,供主控制器线程读取)。

    我会选择选项2。但是,与其使OQL类复杂化,不如创建另一个OQL类实例,方向相反。如果设计简单(如您所建议的那样)这应该是可能的。注意,您需要具有非阻塞写入(或使用to阻塞)否则,就会出现相同的死锁。这实际上很有趣。因为整个队列阻塞唯一的问题是当对客户端的调用生成数据然后返回到控制器时——我真的可以为“响应”添加一个备用数据路径API调用客户端时生成的数据。虽然有点混乱。是的……我应该这样做,因为它允许我在控制器中实现一个设计良好的解决方案。我可以跳过客户端代码的噩梦,它也解决了我对有人无意中重新引入B的担忧ug进入客户端。它还允许我保持Q的简单化,并将复杂性推到一个更有意义的层次。这就是我要做的。现在唯一的问题