我正在研究C ++中的多线程项目,该项目将数据发送到一系列网络连接。这是一些伪代码,用于说明正在发生的事情:
class NetworkManager
{
Thread writer; // responsible for writing data in queues to the network
Queue[] outqueue; // holds data until the network is ready to receive it
Network[] nets; // sockets or whatever
Mutex[] outlock; // protects access to members of outqueue
Mutex managerlock; // protects access to all queues
Condition notifier; // blocks the write thread when there is no data
}
实际上它比这复杂得多,但我已经砍掉了很多不必要的细节。一个重要的细节是网络是速率限制的,并且程序独立于发送数据排队数据的能力是设计的一个特征(程序不必等待处理新数据,因为它在网络写入时阻塞)。
以下是该程序如何与此类进行交互的简要说明。请注意,QueueWriteToNetwork
和DoAdministrativeStuff
在我的实现中由THE SAME外部线程管理。
QueueWriteToNetwork(network, data) // responsibility of external thread
Let i = the index of the network to send to
Lock(outlock[i])
outqueue[i].Add(data)
Unlock(outlock[i])
Signal(notifier)
DoAdministrativeStuff(network, more) // responsibility of external thread
Lock(managerlock)
more.Process() // might do any of the following:
// connect or disconnect networks
// add or remove networks from list
// immediate write data to network, bypassing rate limiting
// other things that I forgot
Unlock(managerlock)
WriterThreadMain() // responsibility of internal write thread
Lock(managerlock)
Loop forever:
Check for data in every queue (locking and unlocking each queue)
If all queues have no data to write:
Wait(notifier, managerlock)
continue
If outqueue[i] has data ready to write
Lock(outlock[i])
Send data from outqueue[i]
outqueue[i].Pop()
Unlock(outqueue[i])
正如您可能会看到的,此方法存在一些问题(例如,如果使用QueueWriteToNetwork
将写入队列到网络,因为WriterThreadMain
正在检查队列是否为空,对Signal(notifier)
的调用可能会被删除,即使有数据就绪,写队列仍可以等待。)
我需要用以下方式来表达这一点:
DoAdministrativeStuff
函数必须能够确保写入程序线程在安全状态下被阻止(即不访问任何队列,队列锁定或网络)我已经探索了使用信号量跟踪写入队列中项目数的可能性。这将解决我之前提到的丢失更新问题。
最后,我的目标是Linux(使用Posix库提供类型pthread_t
,pthread_mutex_t
,pthread_cond_t
和sem_t
),我不在乎关于与Windows的兼容性。另外,请不要推荐Boost。将任何Boost标头拉入我的代码会使编译耗费无法忍受。