IO调度的本质上把多个阻塞集中为一个阻塞,在这一个阻塞上获取事件,发 生“中断”,挂起或者恢复(调度)原先那些本应该阻塞的控制流。在一个 控制流上并发地生产多个超时事件的东东就叫做定时器。
大体上,定时器是一个线程,接受注册超时事件,在任何一个超时事件的条件 满足时发出事件。基本的思路是用一个并发数据结构维护注册的事件,睡一段 时间醒来去看一下这个数据结构,收集满足条件的事件,根据应用上的要求, 做特定的事情(也就是发出事件)。
这里面就有两个选择,第一:选择何种数据结构,第二,怎么睡,睡多久。
关于第一个问题,使用最小堆或者优先队列应该是比较直观的想法。如果假 设比较后来进入的超时请求,应该概率上比先进入的超时请求更加迟到达, 这大部分应该是成立的,优先队列应该效率不错,但这需要评测,这两种数 据结构在一般的假设下都是合理的选择。
第二个问题,关于睡多久,自然是堆或者是队列首元素距离当前的时间,显 然,每次只要睡这么久就绝对不会错过。但是有一个问题就是当有事件注册 进来的时候,它到达的时间可能比当前堆或者队列的首元素的时间还要早, 也就是说注册之后它就是首元素了,那么这时候就要唤醒定时器,通知他更 新自己的睡眠时间。所以我们就用了一个poll做定时器,在poll上监控了一 个socket pair,用来唤醒定时器。