# 基于事件的并发

#### 基础

1. anaging concurrency correctly in multi-threaded applications can be challenging
2. in a multi-threaded application, the developer has little or no control over what is schedule at a given moment in time

Event-based Concurrency 的简单定义：

you simply wait for something (i.e., an “event”) to occur; when it does, you check what type of event it is and do the small amount of work it requires (which may include issuing I/O requests, or scheduling other events for future handling, etc.). That’s it

//伪代码
while (1) {
events = getEvents();
for (e in events)
processEvent(e); // event handler
}


#### 事件循环的API

select() OR poll()
select() 需要注意的：

1. note that it lets you check whether descriptors can be read from as well as written to
2. note the timeout argument

1. Asynchronous I/O
很多现代操作系统都会介绍asynchronous I/O这个新式的硬盘IO处理方式 AIO control block （*nix）
2. 状态管理 UNIX SIGNALS

#### 仍然存在的问题

1. when systems moved from a single CPU to multiple CPUs, some of the simplicity of the event-based approach disappeared
2. it does not integrate well with certain kinds of systems activity, such as paging
3. event-based code can be hard to manage over time, as the exact semantics of various routines changes
比如代码重构 从not block 重构成 block 的程序
4. though asynchronous disk I/O is now possible on most platforms, it has taken a long time to get there , and it never quite integrates with asynchronous network I/O in as simple and uniform a manner as you might think

#### epoll和select/poll的区别联系

1. select，poll，epoll本质上都是同步I/O，因为他们都需要在读写事件就绪后自己负责进行读写，也就是说这个读写过程是阻塞的
2. select，poll实现需要自己不断轮询所有fd集合，直到设备就绪，期间可能要睡眠和唤醒多次交替。而epoll其实也需要调用epoll_wait不断轮询就绪链表，期间也可能多次睡眠和唤醒交替，但是它是设备就绪时，调用回调函数，把就绪fd放入就绪链表中，并唤醒在epoll_wait中进入睡眠的进程。虽然都要睡眠和交替，但是select和poll在“醒着”的时候要遍历整个fd集合，而epoll在“醒着”的时候只要判断一下就绪链表是否为空就行了，这节省了大量的CPU时间。这就是回调机制带来的性能提升。
3. select，poll每次调用都要把fd集合从用户态往内核态拷贝一次，并且要把current往设备等待队列中挂一次，而epoll只要一次拷贝，而且把current往等待队列上挂也只挂一次（在epoll_wait的开始，注意这里的等待队列并不是设备等待队列，只是一个epoll内部定义的等待队列）。这也能节省不少的开销。