C++ 使用boost进程间条件通知的非阻塞共享内存生成器

C++ 使用boost进程间条件通知的非阻塞共享内存生成器,c++,boost,signals,shared-memory,interprocess,C++,Boost,Signals,Shared Memory,Interprocess,我正在尝试开发一个有一个生产者和几个消费者的应用程序。 生产者是一个过程,每个消费者是一个过程。共享资源是共享内存中的某种缓冲区 生产者应完全独立于消费者工作。在任何情况下都不应该阻止它。因此,使用者有责任检查他们从共享内存读取的数据是否有效,并在生产者已经覆盖数据时进行处理。(他们使用某种散列来实现这一点,这并不重要。) 当缓冲区中有新数据可用时,应通知使用者。我认为boost进程间条件适合这个用例。(更合适的是boost signals2,但该库不是以进程间方式工作的) Condition始

我正在尝试开发一个有一个生产者和几个消费者的应用程序。 生产者是一个过程,每个消费者是一个过程。共享资源是共享内存中的某种缓冲区

生产者应完全独立于消费者工作。在任何情况下都不应该阻止它。因此,使用者有责任检查他们从共享内存读取的数据是否有效,并在生产者已经覆盖数据时进行处理。(他们使用某种散列来实现这一点,这并不重要。)

当缓冲区中有新数据可用时,应通知使用者。我认为boost进程间条件适合这个用例。(更合适的是boost signals2,但该库不是以进程间方式工作的)

Condition始终需要一个互斥体。但是我不需要我的制作者中的互斥。在消费者中,我只需要条件为“等待”的互斥

在制作人中只使用codinition#notify#all而不使用互斥可以吗?或者这是对图书馆的滥用


提前感谢

在不保持互斥锁的情况下发出信号是可以的,但在极少数情况下,这可能会导致最坏的行为(线程饥饿)

据我所知,互斥锁下的信令保证了POSIX下侍者的公平调度

这就是说,我认为评论家们在设计中嗅到了过度复杂的味道是对的。我会简化。在需要时进行优化

例如,参见此处:

线程可以调用
pthread\u cond\u broadcast()
pthread\u cond\u signal()
函数,无论它当前是否拥有线程在等待期间调用
pthread\u cond\u wait()
pthread\u timedwait()
与条件变量关联的互斥锁;但是,如果需要可预测的调度行为,则该互斥锁应由调用
pthread\u cond\u broadcast()
pthread\u cond\u signal()
的线程锁定

生产者应完全独立于消费者工作。信息技术 在任何情况下都不应被阻止

为什么不呢?如果不经常锁定,则不会影响性能。您可以在共享内存中有一个数据计数器,并且只锁定对该计数器的访问。数据可以存储在共享内存中的循环缓冲区中,对它的访问不需要锁定,因为使用者使用计数器检查有多少数据可读取。当然,消费者需要足够快地读取数据。如果数据被覆盖,则内部使用者计数器可以重置为进程间计数器的值

生产者还可以使用多个线程存储数据。每个线程都可以在线程开始时计算数据的未来位置,然后在数据存储在线程结束时更新计数器。然后,在将来的位置计算中需要额外的锁定,以便可以在线程之间传递该值

具体而言,非多线程场景的工作原理如下:

Producer loop:
  receive X samples of data
  lock access to interprocess counter, increment the counter, unlock the access
然后,每个使用者都有自己的内部计数器,这样,如果有多少数据可供读取,它就可以与进程间计数器进行比较(只需轮询数据):


你为什么不使用一个管道/先进先出(pipe/FIFO),消费者从中读取,生产者向中写入?你不必处理同步,这将大大简化设计。我使用某种FIFO。但当FIFO中有新数据可用时,我希望得到通知。非阻塞和条件通知是矛盾的。
Consumer loop:
  lock access to interprocess counter, read the counter value, unlock the access
  compare the read value with internal counter
  if values equal // no data available
    sleep, then continue to the beginning of the loop
  else if data overwritten // no need for hashing here, counter can be use to figure that out although doing it this way is probably a bit risky
    set internal counter to the value of the interprocess counter
    then continue to the beginning of the loop
  else
    read available data
    increment internal counter