2012-08-22 146 views
2

当我们想要设计一个通用的事件处理(I/O解复用)或反应堆模式模型。我们使用的底层系统调用是“select”或“poll”。但是这两个系统调用在通用FD上都不是线程安全的。不能用于多线程环境。C++中的多线程事件处理

通过多个I/O的多线程处理事件会是更好的方法。

我可以看到的1种方式是,主线程recv的任何事件并推入到线程池的共享队列中。但工作线程无法通过I/O发送数据导致同步问题。内存溢出也有缺点。

欢迎您提出所有可能的建议。提前致谢。

+0

我会ASIO调查升压一些信息和epoll的替代抽象/ kqueue的,它包装了你的底层细节,并且你可以使用一个更好的界面,它可以处理各种io“事件”,并允许你将自己的事件“发布”到“队列”中进行处理...... – Nim

+0

You' d使用一个线程进行轮询,并将实际的I/O分配给工作线程(超出线程池)。 –

回答

0

一种方法是拥有一个输入线程,一个输出线程,多个工作线程和两个阻塞队列。

输入线程解析输入消息并将它们放入队列1.工作线程全部等待队列1,处理消息并放置它们在队列2中的任何输出。输出线程在队列2上等待并序列化输出。

InputThread: 
    Loop: 
     M = ReadNextMessage 
     Q1.push(M) 

AddOutput(O): 
    Q2.push(O) 

WorkerThread: 
    Loop: 
     M = Q1.pop 
     ProcessMessage(M) using AddOutput as needed 

OutputThread: 
    Loop: 
     O = Q2.pop 
     WriteOutput(O) 

但是,我不知道你的意思是选择不是线程安全吗?所有的系统调用在技术上是线程安全的

这是很老,但还是很有意思的是所谓的“CY10K问题”被称为凯格尔家伙的文章..

http://www.kegel.com/c10k.html

它讨论了不同的方式来构建一个“多io“程序在Linux上的优缺点。

+0

'select'与相同的fd不是线程安全的。你应该读过manuel。 –

+0

@ J-16SDiZ你能解释一下吗?你的意思是如果fd_set在线程之外,然后多线程调用select使用fd_set? –

+0

@ J-16SDiZ:错误。选择是线程安全的,如POSIX手册中所述:http://stackoverflow.com/questions/12084704/select-on-same-fd-from-multiple-sockets –

0

检查出"Producer - Consumer problem",这是线程安全问题的一个非常好的起点。它也可以扩展到多个生产者和多个消费者。

1

大多数Unix系统提供更多的可扩展性的替代选择/民意调查,可以在多线程环境中使用:

但在多线程环境中正确使用它可能会非常棘手,因此您可能需要查看现有的抽象N层像boost.asio

在另一方面,Boost.Asio的确实引入了一些不可忽视的开销 - 我收集关于在http://nginetd.cmeerw.org

+0

谢谢..我会经历这些反思。 – Naveen