muduo::TimerId、Timer、TimerQueue分析

来源:互联网 发布:js中隐藏div 编辑:程序博客网 时间:2024/06/06 11:37

目录(?)[+]

  • Linux时间函数介绍
    • linux中用以获取当前时间的的函数有
    • 定时函数
  • timerfd介绍
  • TimerId介绍
  • Timer
  • TimerQueue

Linux时间函数介绍

linux中用以获取当前时间的的函数有:

time(2) / time_t(秒) 
ftime(3) / struct timeb(毫秒) 
gettimeofday(2) / struct timeval(微秒) 
clock_gettime(2) / struct timespec(微秒)

还有gmtime / localtime / timegm / mktime / strftime / struct tm等与当前时间无关的时间格式转换函数。

定时函数

sleep(3) 
alarm(3) 
usleep(3) 
nanosleep(2) 
clock_nanosleep(2) 
gettimer(2) / settitimer(2) 
timer_create(2) / timer_settime(2) / tiemr_gettime(2) / timer_delete(2) 
timerfd_create(2) / timerfd_gettime(2) / timerfd_settime(2)

取舍如下: 
1、计时只使用gettimeofday(2)来获取当前时间。 
2、定时只使用timerfd_*系列函数来处理定时任务。

timerfd介绍

这节介绍muduo中定时器的实现。先看一个2.6内核新增的有关定时的系统调用,基于这几个系统调用可以实现基于文件描述符的定时器。即可是定时,使文件描述符在某一特定时间可读。

<code class="hljs vala has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <sys/timerfd.h></span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> timerfd_create(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> clockid, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> flags);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> timerfd_settime(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> fd, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> flags,         onst <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> itimerspec *new_value,         <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> itimerspec *old_value);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> timerfd_gettime(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> fd, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> itimerspec *curr_value);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

1、timerfd_create用于创建一个定时器文件,函数返回值是一个文件句柄fd。 
2、timerfd_settime用于设置新的超时时间,并开始计时。flag为0表示相对时间,为1表示绝对时间。new_value为这次设置的新时间,old_value为上次设置的时间。返回0表示设置成功。 
3、timerfd_gettime用于获得定时器距离下次超时还剩下的时间。如果调用时定时器已经到期,并且该定时器处于循环模式(设置超时时间时struct itimerspec::it_interval不为0),那么调用此函数之后定时器重新开始计时。

TimerId介绍

TimerId非常简单,它被设计用来取消Timer的,它的结构很简单,只有一个Timer指针和其序列号。

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">class TimerId : <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> muduo::copyable{ <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:  <span class="hljs-title" style="box-sizing: border-box;">TimerId</span>()    : <span class="hljs-title" style="box-sizing: border-box;">timer_</span>(NULL),      <span class="hljs-title" style="box-sizing: border-box;">sequence_</span>(0)  {  }  TimerId(Timer* timer, int64_t seq)    : timer_(timer),      sequence_(seq)  {  }  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// default copy-ctor, dtor and assignment are okay</span>  friend class TimerQueue; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span>:  Timer* timer_;  int64_t sequence_;};</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li></ul>

TimerQueue为其友元,可以操作其私有数据。

Timer

Timer封装了定时器的一些参数,例如超时回调函数、超时时间、定时器是否重复、重复间隔时间、定时器的序列号。其函数大都是设置这些参数,run()用来调用回调函数,restart()用来重启定时器(如果设置为重复)。其源码相对简单 
Timer.h

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">class Timer : boost::noncopyable{ <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:  <span class="hljs-title" style="box-sizing: border-box;">Timer</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> TimerCallback& cb, Timestamp when, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> interval)    : <span class="hljs-title" style="box-sizing: border-box;">callback_</span>(cb),//回调函数      <span class="hljs-title" style="box-sizing: border-box;">expiration_</span>(when),//超时时间      <span class="hljs-title" style="box-sizing: border-box;">interval_</span>(interval),//如果重复,间隔时间      <span class="hljs-title" style="box-sizing: border-box;">repeat_</span>(interval > 0.0),//是否重复      <span class="hljs-title" style="box-sizing: border-box;">sequence_</span>(s_numCreated_.<span class="hljs-title" style="box-sizing: border-box;">incrementAndGet</span>())//当前定时器的序列号  { }<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#ifdef __GXX_EXPERIMENTAL_CXX0X__</span>  Timer(TimerCallback&& cb, Timestamp when, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> interval)    : callback_(std::move(cb)),      expiration_(when),      interval_(interval),      repeat_(interval > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.0</span>),      sequence_(s_numCreated_.incrementAndGet())  { }<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#<span class="hljs-keyword" style="box-sizing: border-box;">endif</span></span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> run() <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//超时时调用回调函数</span>  {    callback_();  }  Timestamp expiration() <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span>  { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> expiration_; }  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">bool</span> repeat() <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> repeat_; }  int64_t sequence() <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> sequence_; }  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> restart(Timestamp now);  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> int64_t numCreated() { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> s_numCreated_.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">get</span>(); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span>:  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> TimerCallback callback_;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//回调函数</span>  Timestamp expiration_;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//超时时间(绝对时间)</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> interval_;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//间隔多久重新闹铃</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">bool</span> repeat_;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//是否重复</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> int64_t sequence_;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Timer序号</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> AtomicInt64 s_numCreated_;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//创建Timer序号使用,static</span>};</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li></ul>

Timer.cc

<code class="hljs lasso has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">AtomicInt64 Timer<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;">::s_numCreated_</span>;<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">void</span> Timer<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;">::restart</span>(Timestamp now){  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (repeat_)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果设置重复,则重新添加</span>  {    expiration_ <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> addTime(now, interval_);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//将now和interval_相加</span>  }  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>  {    expiration_ <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> Timestamp<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;">::invalid</span>();  }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>

TimerQueue

虽然TimerQueue中有Queue,但是其实现时基于Set的,而不是Queue。这样可以高效地插入、删除定时器,且找到当前已经超时的定时器。TimerQueue的public接口只有两个,添加和删除。

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> addTimerInLoop(Timer* timer);<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> cancelInLoop(TimerId timerId);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

内部有channel,和timerfd关联。添加新的Timer后,在超时后,timerfd可读,会处理channel事件,之后调用Timer的回调函数;在timerfd的事件处理后,还有检查一遍超时定时器,如果其属性为重复还有再次添加到定时器集合中。

内部有两种类型的Set

<code class="hljs cpp has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typedef</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::pair<Timestamp, Timer*> Entry;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typedef</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::<span class="hljs-stl_container" style="box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">set</span><Entry></span> TimerList;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typedef</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::pair<Timer*, int64_t> ActiveTimer;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typedef</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::<span class="hljs-stl_container" style="box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">set</span><ActiveTimer></span> ActiveTimerSet;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

一个Set元素类型为超时事件和Timer*指针;另一种为Timer*指针和定时器序列号。

下面是源码 
TimerQueue.h

<code class="hljs cpp has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> TimerQueue : boost::noncopyable{ <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:  TimerQueue(EventLoop* loop);  ~TimerQueue();  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">///</span>  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/// Schedules the callback to be run at given time,</span>  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/// repeats if @c interval > 0.0.</span>  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">///</span>  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/// Must be thread safe. Usually be called from other threads.</span>  TimerId addTimer(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> TimerCallback& cb,                   Timestamp when,                   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> interval);<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#ifdef __GXX_EXPERIMENTAL_CXX0X__</span>  TimerId addTimer(TimerCallback&& cb,                   Timestamp when,                   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> interval);<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#endif</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> cancel(TimerId timerId); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span>:  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// FIXME: use unique_ptr<Timer> instead of raw pointers.</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typedef</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::pair<Timestamp, Timer*> Entry;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//std::pair支持比较运算</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typedef</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::<span class="hljs-stl_container" style="box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">set</span><Entry></span> TimerList;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//元素为超时时间和指向超时的定时器</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typedef</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::pair<Timer*, int64_t> ActiveTimer;  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typedef</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::<span class="hljs-stl_container" style="box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">set</span><ActiveTimer></span> ActiveTimerSet;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//元素为定时器和其序列号</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> addTimerInLoop(Timer* timer);  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> cancelInLoop(TimerId timerId);  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// called when timerfd alarms</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> handleRead();  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// move out all expired timers</span>  <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::<span class="hljs-stl_container" style="box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">vector</span><Entry></span> getExpired(Timestamp now);  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> reset(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::<span class="hljs-stl_container" style="box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">vector</span><Entry></span>& expired, Timestamp now);  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">bool</span> insert(Timer* timer);  EventLoop* loop_;  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> timerfd_;  Channel timerfdChannel_;  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Timer list sorted by expiration</span>  TimerList timers_;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//定时器集合</span>  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// for cancel()</span>  ActiveTimerSet activeTimers_;  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">bool</span> callingExpiredTimers_; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* atomic */</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//是否正在处理超时事件</span>  ActiveTimerSet cancelingTimers_;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//取消了的定时器的集合</span>};</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li></ul>

TimerQueue.cpp

<code class="hljs cpp has-numbering" style="color: inherit; display: block; padding: 0px; background: transparent; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> createTimerfd()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//创建timerfd</span>{  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> timerfd = ::timerfd_create(CLOCK_MONOTONIC,                                 TFD_NONBLOCK | TFD_CLOEXEC);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//非阻塞</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (timerfd < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>)  {    LOG_SYSFATAL << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Failed in timerfd_create"</span>;  }  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> timerfd;}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> timespec howMuchTimeFromNow(Timestamp when)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//现在距离超时时间when还有多久</span>{  int64_t microseconds = when.microSecondsSinceEpoch()                         - Timestamp::now().microSecondsSinceEpoch();  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (microseconds < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>)  {    microseconds = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>;  }  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> timespec ts;  ts.tv_sec = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static_cast</span><time_t>(      microseconds / Timestamp::kMicroSecondsPerSecond);  ts.tv_nsec = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static_cast</span><<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span>>(      (microseconds % Timestamp::kMicroSecondsPerSecond) * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1000</span>);  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> ts;}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> readTimerfd(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> timerfd, Timestamp now)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//处理超时事件。超时后,timerfd变为可读</span>{  uint64_t howmany;  ssize_t n = ::read(timerfd, &howmany, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span> howmany);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//读timerfd,howmany为超时次数</span>  LOG_TRACE << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"TimerQueue::handleRead() "</span> << howmany << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" at "</span> << now.toString();  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (n != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span> howmany)  {    LOG_ERROR << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"TimerQueue::handleRead() reads "</span> << n << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" bytes instead of 8"</span>;  }}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> resetTimerfd(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> timerfd, Timestamp expiration)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//重新设置定时器</span>{  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// wake up loop by timerfd_settime()</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> itimerspec newValue;  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> itimerspec oldValue;  bzero(&newValue, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span> newValue);  bzero(&oldValue, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span> oldValue);  newValue.it_value = howMuchTimeFromNow(expiration);  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> ret = ::timerfd_settime(timerfd, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, &newValue, &oldValue);  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (ret)  {    LOG_SYSERR << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"timerfd_settime()"</span>;  }}TimerQueue::TimerQueue(EventLoop* loop)  : loop_(loop),    timerfd_(createTimerfd()),<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//创建timerfd</span>    timerfdChannel_(loop, timerfd_),<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//timerfd相关的channel</span>    timers_(),    callingExpiredTimers_(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>){  timerfdChannel_.setReadCallback(      boost::bind(&TimerQueue::handleRead, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>));<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置回调函数,读timerfd</span>  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// we are always reading the timerfd, we disarm it with timerfd_settime.</span>  timerfdChannel_.enableReading();<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//timerfd对应的channel监听事件为可读事件</span>}TimerQueue::~TimerQueue(){  timerfdChannel_.disableAll();  timerfdChannel_.remove();  ::close(timerfd_);  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// do not remove channel, since we're in EventLoop::dtor();</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (TimerList::iterator it = timers_.begin();      it != timers_.end(); ++it)  {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">delete</span> it->second;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//释放Timer*</span>  }}TimerId TimerQueue::addTimer(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> TimerCallback& cb,<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//添加新的定时器</span>                             Timestamp when,                             <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> interval){  Timer* timer = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Timer(cb, when, interval);  loop_->runInLoop(      boost::bind(&TimerQueue::addTimerInLoop, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>, timer));  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> TimerId(timer, timer->sequence());}<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#ifdef __GXX_EXPERIMENTAL_CXX0X__</span>TimerId TimerQueue::addTimer(TimerCallback&& cb,                             Timestamp when,                             <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> interval){  Timer* timer = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Timer(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::move(cb), when, interval);  loop_->runInLoop(      boost::bind(&TimerQueue::addTimerInLoop, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>, timer));  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> TimerId(timer, timer->sequence());}<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#endif</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> TimerQueue::cancel(TimerId timerId){  loop_->runInLoop(      boost::bind(&TimerQueue::cancelInLoop, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>, timerId));}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> TimerQueue::addTimerInLoop(Timer* timer){  loop_->assertInLoopThread();  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">bool</span> earliestChanged = insert(timer);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//插入成功,则启动</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (earliestChanged)  {    resetTimerfd(timerfd_, timer->expiration());<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//启动定时器</span>  }}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> TimerQueue::cancelInLoop(TimerId timerId){  loop_->assertInLoopThread();  assert(timers_.size() == activeTimers_.size());  ActiveTimer timer(timerId.timer_, timerId.sequence_);  ActiveTimerSet::iterator it = activeTimers_.find(timer);  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (it != activeTimers_.end())<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//要取消的在当前激活的Timer集合中</span>  {    size_t n = timers_.erase(Entry(it->first->expiration(), it->first));<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//在timers_中取消</span>    assert(n == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>); (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)n;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">delete</span> it->first; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// FIXME: no delete please</span>    activeTimers_.erase(it);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//在activeTimers_中取消</span>  }  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (callingExpiredTimers_)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果正在执行超时定时器的回调函数,则加入到cancelingTimers集合中</span>  {    cancelingTimers_.insert(timer);  }  assert(timers_.size() == activeTimers_.size());}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> TimerQueue::handleRead()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//处理timerfd读事件</span>{  loop_->assertInLoopThread();  Timestamp now(Timestamp::now());  readTimerfd(timerfd_, now);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//读timerfd</span></code><code class="hljs cpp has-numbering" style="display: block; padding: 0px; background: transparent; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">                             <span style="color:#3333ff;">//这句就是意思一下,读到的数据没有用,但不能不读,防止一直被epoll/poll“激活”</span>  <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span><span style="color:rgba(0, 0, 0, 0);">::</span><span class="hljs-stl_container" style="color: inherit; box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">vector</span><Entry></span><span style="color:rgba(0, 0, 0, 0);"> expired = getExpired(now);</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//找到超时定时器</span><span style="color:rgba(0, 0, 0, 0);">  callingExpiredTimers_ = </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span><span style="color:rgba(0, 0, 0, 0);">;  cancelingTimers_.clear();  </span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// safe to callback outside critical section</span><span style="color:rgba(0, 0, 0, 0);">  </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span><span style="color:rgba(0, 0, 0, 0);"> (</span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span><span style="color:rgba(0, 0, 0, 0);">::</span><span class="hljs-stl_container" style="color: inherit; box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">vector</span><Entry></span><span style="color:rgba(0, 0, 0, 0);">::iterator it = expired.begin();      it != expired.end(); ++it)  {    it->second->run();</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//调用timer的回调函数</span><span style="color:rgba(0, 0, 0, 0);">  }  callingExpiredTimers_ = </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span><span style="color:rgba(0, 0, 0, 0);">;  reset(expired, now);</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//把重复的定时器重新加入到定时器中</span><span style="color:rgba(0, 0, 0, 0);">}</span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span><span style="color:rgba(0, 0, 0, 0);">::</span><span class="hljs-stl_container" style="color: inherit; box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">vector</span><TimerQueue::Entry></span><span style="color:rgba(0, 0, 0, 0);"> TimerQueue::getExpired(Timestamp now){  assert(timers_.size() == activeTimers_.size());  </span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span><span style="color:rgba(0, 0, 0, 0);">::</span><span class="hljs-stl_container" style="color: inherit; box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">vector</span><Entry></span><span style="color:rgba(0, 0, 0, 0);"> expired;  Entry sentry(now, </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">reinterpret_cast</span><span style="color:rgba(0, 0, 0, 0);"><Timer*>(UINTPTR_MAX));  TimerList::iterator end = timers_.lower_bound(sentry);</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//返回第一个大于等于now的迭代器,小于now的都已经超时</span><span style="color:rgba(0, 0, 0, 0);">  assert(end == timers_.end() || now < end->first);  </span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span><span style="color:rgba(0, 0, 0, 0);">::copy(timers_.begin(), end, back_inserter(expired));</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//[begin end)之间的元素追加到expired末尾</span><span style="color:rgba(0, 0, 0, 0);">  timers_.erase(timers_.begin(), end);</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//删除超时定时器</span><span style="color:rgba(0, 0, 0, 0);">  </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span><span style="color:rgba(0, 0, 0, 0);"> (</span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span><span style="color:rgba(0, 0, 0, 0);">::</span><span class="hljs-stl_container" style="color: inherit; box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">vector</span><Entry></span><span style="color:rgba(0, 0, 0, 0);">::iterator it = expired.begin();      it != expired.end(); ++it)  {    ActiveTimer timer(it->second, it->second->sequence());    size_t n = activeTimers_.erase(timer);</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//删除超时定时器</span><span style="color:rgba(0, 0, 0, 0);">    assert(n == </span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span><span style="color:rgba(0, 0, 0, 0);">); (</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span><span style="color:rgba(0, 0, 0, 0);">)n;  }  assert(timers_.size() == activeTimers_.size());  </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span><span style="color:rgba(0, 0, 0, 0);"> expired;}</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span><span style="color:rgba(0, 0, 0, 0);"> TimerQueue::reset(</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span><span style="color:rgba(0, 0, 0, 0);"> </span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span><span style="color:rgba(0, 0, 0, 0);">::</span><span class="hljs-stl_container" style="color: inherit; box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">vector</span><Entry></span><span style="color:rgba(0, 0, 0, 0);">& expired, Timestamp now){  Timestamp nextExpire;  </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span><span style="color:rgba(0, 0, 0, 0);"> (</span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span><span style="color:rgba(0, 0, 0, 0);">::</span><span class="hljs-stl_container" style="color: inherit; box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">vector</span><Entry></span><span style="color:rgba(0, 0, 0, 0);">::const_iterator it = expired.begin();//有些任务是运行runEvery加进来的,这些任务要重复运行      it != expired.end(); ++it)                               //所以要把这些任务重新加进set里。  {    ActiveTimer timer(it->second, it->second->sequence());    </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span><span style="color:rgba(0, 0, 0, 0);"> (it->second->repeat()</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//重复</span><span style="color:rgba(0, 0, 0, 0);">        && cancelingTimers_.find(timer) == cancelingTimers_.end())</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//且不在cancelingTimers_集合中</span><span style="color:rgba(0, 0, 0, 0);">    {      it->second->restart(now);</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//重启定时器</span><span style="color:rgba(0, 0, 0, 0);">      insert(it->second);</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//重新插入倒timers_和activeTimers</span><span style="color:rgba(0, 0, 0, 0);">    }    </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span><span style="color:rgba(0, 0, 0, 0);">    {      </span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// FIXME move to a free list</span><span style="color:rgba(0, 0, 0, 0);">      </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">delete</span><span style="color:rgba(0, 0, 0, 0);"> it->second; </span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// FIXME: no delete please</span><span style="color:rgba(0, 0, 0, 0);">    }  }  </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span><span style="color:rgba(0, 0, 0, 0);"> (!timers_.empty())  {    nextExpire = timers_.begin()->second->expiration();  }  </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span><span style="color:rgba(0, 0, 0, 0);"> (nextExpire.valid())  {    resetTimerfd(timerfd_, nextExpire);  }}</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">bool</span><span style="color:rgba(0, 0, 0, 0);"> TimerQueue::insert(Timer* timer)</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//插入一个timer</span><span style="color:rgba(0, 0, 0, 0);">{  loop_->assertInLoopThread();  assert(timers_.size() == activeTimers_.size());  </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">bool</span><span style="color:rgba(0, 0, 0, 0);"> earliestChanged = </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span><span style="color:rgba(0, 0, 0, 0);">;  Timestamp when = timer->expiration();  TimerList::iterator it = timers_.begin();  </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span><span style="color:rgba(0, 0, 0, 0);"> (it == timers_.end() || when < it->first)</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//当前插入的定时器是否时最早到时的</span><span style="color:rgba(0, 0, 0, 0);">  {                                           </span><span style="color:#3366ff;">//要是set里最早截止(it->first)的那个没when早,那么需要更新定时器</span><span style="color:rgba(0, 0, 0, 0);">    earliestChanged = </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span><span style="color:rgba(0, 0, 0, 0);">;                   </span><span style="color:#3366ff;">//这里好像是因为handleread那个地方用now更新定时器造成的。</span><span style="color:rgba(0, 0, 0, 0);">  }  {    </span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span><span style="color:rgba(0, 0, 0, 0);">::pair<TimerList::iterator, </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">bool</span><span style="color:rgba(0, 0, 0, 0);">> result      = timers_.insert(Entry(when, timer));    assert(result.second); (</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span><span style="color:rgba(0, 0, 0, 0);">)result;</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//为什么(void)result</span><span style="color:rgba(0, 0, 0, 0);">  }  {    </span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span><span style="color:rgba(0, 0, 0, 0);">::pair<ActiveTimerSet::iterator, </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">bool</span><span style="color:rgba(0, 0, 0, 0);">> result      = activeTimers_.insert(ActiveTimer(timer, timer->sequence()));    assert(result.second); (</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span><span style="color:rgba(0, 0, 0, 0);">)result;  }  assert(timers_.size() == activeTimers_.size());  </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span><span style="color:rgba(0, 0, 0, 0);"> earliestChanged;}</span></code><ul class="pre-numbering" style="color: rgb(51, 51, 51); box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li><li style="box-sizing: border-box; padding: 0px 5px;">122</li><li style="box-sizing: border-box; padding: 0px 5px;">123</li><li style="box-sizing: border-box; padding: 0px 5px;">124</li><li style="box-sizing: border-box; padding: 0px 5px;">125</li><li style="box-sizing: border-box; padding: 0px 5px;">126</li><li style="box-sizing: border-box; padding: 0px 5px;">127</li><li style="box-sizing: border-box; padding: 0px 5px;">128</li><li style="box-sizing: border-box; padding: 0px 5px;">129</li><li style="box-sizing: border-box; padding: 0px 5px;">130</li><li style="box-sizing: border-box; padding: 0px 5px;">131</li><li style="box-sizing: border-box; padding: 0px 5px;">132</li><li style="box-sizing: border-box; padding: 0px 5px;">133</li><li style="box-sizing: border-box; padding: 0px 5px;">134</li><li style="box-sizing: border-box; padding: 0px 5px;">135</li><li style="box-sizing: border-box; padding: 0px 5px;">136</li><li style="box-sizing: border-box; padding: 0px 5px;">137</li><li style="box-sizing: border-box; padding: 0px 5px;">138</li><li style="box-sizing: border-box; padding: 0px 5px;">139</li><li style="box-sizing: border-box; padding: 0px 5px;">140</li><li style="box-sizing: border-box; padding: 0px 5px;">141</li><li style="box-sizing: border-box; padding: 0px 5px;">142</li><li style="box-sizing: border-box; padding: 0px 5px;">143</li><li style="box-sizing: border-box; padding: 0px 5px;">144</li><li style="box-sizing: border-box; padding: 0px 5px;">145</li><li style="box-sizing: border-box; padding: 0px 5px;">146</li><li style="box-sizing: border-box; padding: 0px 5px;">147</li><li style="box-sizing: border-box; padding: 0px 5px;">148</li><li style="box-sizing: border-box; padding: 0px 5px;">149</li><li style="box-sizing: border-box; padding: 0px 5px;">150</li><li style="box-sizing: border-box; padding: 0px 5px;">151</li><li style="box-sizing: border-box; padding: 0px 5px;">152</li><li style="box-sizing: border-box; padding: 0px 5px;">153</li><li style="box-sizing: border-box; padding: 0px 5px;">154</li><li style="box-sizing: border-box; padding: 0px 5px;">155</li><li style="box-sizing: border-box; padding: 0px 5px;">156</li><li style="box-sizing: border-box; padding: 0px 5px;">157</li><li style="box-sizing: border-box; padding: 0px 5px;">158</li><li style="box-sizing: border-box; padding: 0px 5px;">159</li><li style="box-sizing: border-box; padding: 0px 5px;">160</li><li style="box-sizing: border-box; padding: 0px 5px;">161</li><li style="box-sizing: border-box; padding: 0px 5px;">162</li><li style="box-sizing: border-box; padding: 0px 5px;">163</li><li style="box-sizing: border-box; padding: 0px 5px;">164</li><li style="box-sizing: border-box; padding: 0px 5px;">165</li><li style="box-sizing: border-box; padding: 0px 5px;">166</li><li style="box-sizing: border-box; padding: 0px 5px;">167</li><li style="box-sizing: border-box; padding: 0px 5px;">168</li><li style="box-sizing: border-box; padding: 0px 5px;">169</li><li style="box-sizing: border-box; padding: 0px 5px;">170</li><li style="box-sizing: border-box; padding: 0px 5px;">171</li><li style="box-sizing: border-box; padding: 0px 5px;">172</li><li style="box-sizing: border-box; padding: 0px 5px;">173</li><li style="box-sizing: border-box; padding: 0px 5px;">174</li><li style="box-sizing: border-box; padding: 0px 5px;">175</li><li style="box-sizing: border-box; padding: 0px 5px;">176</li><li style="box-sizing: border-box; padding: 0px 5px;">177</li><li style="box-sizing: border-box; padding: 0px 5px;">178</li><li style="box-sizing: border-box; padding: 0px 5px;">179</li><li style="box-sizing: border-box; padding: 0px 5px;">180</li><li style="box-sizing: border-box; padding: 0px 5px;">181</li><li style="box-sizing: border-box; padding: 0px 5px;">182</li><li style="box-sizing: border-box; padding: 0px 5px;">183</li><li style="box-sizing: border-box; padding: 0px 5px;">184</li><li style="box-sizing: border-box; padding: 0px 5px;">185</li><li style="box-sizing: border-box; padding: 0px 5px;">186</li><li style="box-sizing: border-box; padding: 0px 5px;">187</li><li style="box-sizing: border-box; padding: 0px 5px;">188</li><li style="box-sizing: border-box; padding: 0px 5px;">189</li><li style="box-sizing: border-box; padding: 0px 5px;">190</li><li style="box-sizing: border-box; padding: 0px 5px;">191</li><li style="box-sizing: border-box; padding: 0px 5px;">192</li><li style="box-sizing: border-box; padding: 0px 5px;">193</li><li style="box-sizing: border-box; padding: 0px 5px;">194</li><li style="box-sizing: border-box; padding: 0px 5px;">195</li><li style="box-sizing: border-box; padding: 0px 5px;">196</li><li style="box-sizing: border-box; padding: 0px 5px;">197</li><li style="box-sizing: border-box; padding: 0px 5px;">198</li><li style="box-sizing: border-box; padding: 0px 5px;">199</li><li style="box-sizing: border-box; padding: 0px 5px;">200</li><li style="box-sizing: border-box; padding: 0px 5px;">201</li><li style="box-sizing: border-box; padding: 0px 5px;">202</li><li style="box-sizing: border-box; padding: 0px 5px;">203</li><li style="box-sizing: border-box; padding: 0px 5px;">204</li><li style="box-sizing: border-box; padding: 0px 5px;">205</li><li style="box-sizing: border-box; padding: 0px 5px;">206</li><li style="box-sizing: border-box; padding: 0px 5px;">207</li><li style="box-sizing: border-box; padding: 0px 5px;">208</li><li style="box-sizing: border-box; padding: 0px 5px;">209</li><li style="box-sizing: border-box; padding: 0px 5px;">210</li><li style="box-sizing: border-box; padding: 0px 5px;">211</li><li style="box-sizing: border-box; padding: 0px 5px;">212</li><li style="box-sizing: border-box; padding: 0px 5px;">213</li><li style="box-sizing: border-box; padding: 0px 5px;">214</li><li style="box-sizing: border-box; padding: 0px 5px;">215</li><li style="box-sizing: border-box; padding: 0px 5px;">216</li><li style="box-sizing: border-box; padding: 0px 5px;">217</li><li style="box-sizing: border-box; padding: 0px 5px;">218</li><li style="box-sizing: border-box; padding: 0px 5px;">219</li><li style="box-sizing: border-box; padding: 0px 5px;">220</li><li style="box-sizing: border-box; padding: 0px 5px;">221</li><li style="box-sizing: border-box; padding: 0px 5px;">222</li><li style="box-sizing: border-box; padding: 0px 5px;">223</li><li style="box-sizing: border-box; padding: 0px 5px;">224</li><li style="box-sizing: border-box; padding: 0px 5px;">225</li><li style="box-sizing: border-box; padding: 0px 5px;">226</li><li style="box-sizing: border-box; padding: 0px 5px;">227</li><li style="box-sizing: border-box; padding: 0px 5px;">228</li><li style="box-sizing: border-box; padding: 0px 5px;">229</li><li style="box-sizing: border-box; padding: 0px 5px;">230</li><li style="box-sizing: border-box; padding: 0px 5px;">231</li><li style="box-sizing: border-box; padding: 0px 5px;">232</li><li style="box-sizing: border-box; padding: 0px 5px;">233</li><li style="box-sizing: border-box; padding: 0px 5px;">234</li><li style="box-sizing: border-box; padding: 0px 5px;">235</li><li style="box-sizing: border-box; padding: 0px 5px;">236</li><li style="box-sizing: border-box; padding: 0px 5px;">237</li><li style="box-sizing: border-box; padding: 0px 5px;">238</li><li style="box-sizing: border-box; padding: 0px 5px;">239</li></ul><ul class="pre-numbering" style="color: rgb(51, 51, 51); box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li><li style="box-sizing: border-box; padding: 0px 5px;">122</li><li style="box-sizing: border-box; padding: 0px 5px;">123</li><li style="box-sizing: border-box; padding: 0px 5px;">124</li><li style="box-sizing: border-box; padding: 0px 5px;">125</li><li style="box-sizing: border-box; padding: 0px 5px;">126</li><li style="box-sizing: border-box; padding: 0px 5px;">127</li><li style="box-sizing: border-box; padding: 0px 5px;">128</li><li style="box-sizing: border-box; padding: 0px 5px;">129</li><li style="box-sizing: border-box; padding: 0px 5px;">130</li><li style="box-sizing: border-box; padding: 0px 5px;">131</li><li style="box-sizing: border-box; padding: 0px 5px;">132</li><li style="box-sizing: border-box; padding: 0px 5px;">133</li><li style="box-sizing: border-box; padding: 0px 5px;">134</li><li style="box-sizing: border-box; padding: 0px 5px;">135</li><li style="box-sizing: border-box; padding: 0px 5px;">136</li><li style="box-sizing: border-box; padding: 0px 5px;">137</li><li style="box-sizing: border-box; padding: 0px 5px;">138</li><li style="box-sizing: border-box; padding: 0px 5px;">139</li><li style="box-sizing: border-box; padding: 0px 5px;">140</li><li style="box-sizing: border-box; padding: 0px 5px;">141</li><li style="box-sizing: border-box; padding: 0px 5px;">142</li><li style="box-sizing: border-box; padding: 0px 5px;">143</li><li style="box-sizing: border-box; padding: 0px 5px;">144</li><li style="box-sizing: border-box; padding: 0px 5px;">145</li><li style="box-sizing: border-box; padding: 0px 5px;">146</li><li style="box-sizing: border-box; padding: 0px 5px;">147</li><li style="box-sizing: border-box; padding: 0px 5px;">148</li><li style="box-sizing: border-box; padding: 0px 5px;">149</li><li style="box-sizing: border-box; padding: 0px 5px;">150</li><li style="box-sizing: border-box; padding: 0px 5px;">151</li><li style="box-sizing: border-box; padding: 0px 5px;">152</li><li style="box-sizing: border-box; padding: 0px 5px;">153</li><li style="box-sizing: border-box; padding: 0px 5px;">154</li><li style="box-sizing: border-box; padding: 0px 5px;">155</li><li style="box-sizing: border-box; padding: 0px 5px;">156</li><li style="box-sizing: border-box; padding: 0px 5px;">157</li><li style="box-sizing: border-box; padding: 0px 5px;">158</li><li style="box-sizing: border-box; padding: 0px 5px;">159</li><li style="box-sizing: border-box; padding: 0px 5px;">160</li><li style="box-sizing: border-box; padding: 0px 5px;">161</li><li style="box-sizing: border-box; padding: 0px 5px;">162</li><li style="box-sizing: border-box; padding: 0px 5px;">163</li><li style="box-sizing: border-box; padding: 0px 5px;">164</li><li style="box-sizing: border-box; padding: 0px 5px;">165</li><li style="box-sizing: border-box; padding: 0px 5px;">166</li><li style="box-sizing: border-box; padding: 0px 5px;">167</li><li style="box-sizing: border-box; padding: 0px 5px;">168</li><li style="box-sizing: border-box; padding: 0px 5px;">169</li><li style="box-sizing: border-box; padding: 0px 5px;">170</li><li style="box-sizing: border-box; padding: 0px 5px;">171</li><li style="box-sizing: border-box; padding: 0px 5px;">172</li><li style="box-sizing: border-box; padding: 0px 5px;">173</li><li style="box-sizing: border-box; padding: 0px 5px;">174</li><li style="box-sizing: border-box; padding: 0px 5px;">175</li><li style="box-sizing: border-box; padding: 0px 5px;">176</li><li style="box-sizing: border-box; padding: 0px 5px;">177</li><li style="box-sizing: border-box; padding: 0px 5px;">178</li><li style="box-sizing: border-box; padding: 0px 5px;">179</li><li style="box-sizing: border-box; padding: 0px 5px;">180</li><li style="box-sizing: border-box; padding: 0px 5px;">181</li><li style="box-sizing: border-box; padding: 0px 5px;">182</li><li style="box-sizing: border-box; padding: 0px 5px;">183</li><li style="box-sizing: border-box; padding: 0px 5px;">184</li><li style="box-sizing: border-box; padding: 0px 5px;">185</li><li style="box-sizing: border-box; padding: 0px 5px;">186</li><li style="box-sizing: border-box; padding: 0px 5px;">187</li><li style="box-sizing: border-box; padding: 0px 5px;">188</li><li style="box-sizing: border-box; padding: 0px 5px;">189</li><li style="box-sizing: border-box; padding: 0px 5px;">190</li><li style="box-sizing: border-box; padding: 0px 5px;">191</li><li style="box-sizing: border-box; padding: 0px 5px;">192</li><li style="box-sizing: border-box; padding: 0px 5px;">193</li><li style="box-sizing: border-box; padding: 0px 5px;">194</li><li style="box-sizing: border-box; padding: 0px 5px;">195</li><li style="box-sizing: border-box; padding: 0px 5px;">196</li><li style="box-sizing: border-box; padding: 0px 5px;">197</li><li style="box-sizing: border-box; padding: 0px 5px;">198</li><li style="box-sizing: border-box; padding: 0px 5px;">199</li><li style="box-sizing: border-box; padding: 0px 5px;">200</li><li style="box-sizing: border-box; padding: 0px 5px;">201</li><li style="box-sizing: border-box; padding: 0px 5px;">202</li><li style="box-sizing: border-box; padding: 0px 5px;">203</li><li style="box-sizing: border-box; padding: 0px 5px;">204</li><li style="box-sizing: border-box; padding: 0px 5px;">205</li><li style="box-sizing: border-box; padding: 0px 5px;">206</li><li style="box-sizing: border-box; padding: 0px 5px;">207</li><li style="box-sizing: border-box; padding: 0px 5px;">208</li><li style="box-sizing: border-box; padding: 0px 5px;">209</li><li style="box-sizing: border-box; padding: 0px 5px;">210</li><li style="box-sizing: border-box; padding: 0px 5px;">211</li><li style="box-sizing: border-box; padding: 0px 5px;">212</li><li style="box-sizing: border-box; padding: 0px 5px;">213</li><li style="box-sizing: border-box; padding: 0px 5px;">214</li><li style="box-sizing: border-box; padding: 0px 5px;">215</li><li style="box-sizing: border-box; padding: 0px 5px;">216</li><li style="box-sizing: border-box; padding: 0px 5px;">217</li><li style="box-sizing: border-box; padding: 0px 5px;">218</li><li style="box-sizing: border-box; padding: 0px 5px;">219</li><li style="box-sizing: border-box; padding: 0px 5px;">220</li><li style="box-sizing: border-box; padding: 0px 5px;">221</li><li style="box-sizing: border-box; padding: 0px 5px;">222</li><li style="box-sizing: border-box; padding: 0px 5px;">223</li><li style="box-sizing: border-box; padding: 0px 5px;">224</li><li style="box-sizing: border-box; padding: 0px 5px;">225</li><li style="box-sizing: border-box; padding: 0px 5px;">226</li><li style="box-sizing: border-box; padding: 0px 5px;">227</li><li style="box-sizing: border-box; padding: 0px 5px;">228</li><li style="box-sizing: border-box; padding: 0px 5px;">229</li><li style="box-sizing: border-box; padding: 0px 5px;">230</li><li style="box-sizing: border-box; padding: 0px 5px;">231</li><li style="box-sizing: border-box; padding: 0px 5px;">232</li><li style="box-sizing: border-box; padding: 0px 5px;">233</li><li style="box-sizing: border-box; padding: 0px 5px;">234</li><li style="box-sizing: border-box; padding: 0px 5px;">235</li><li style="box-sizing: border-box; padding: 0px 5px;">236</li><li style="box-sizing: border-box; padding: 0px 5px;">237</li><li style="box-sizing: border-box; padding: 0px 5px;">238</li><li style="box-sizing: border-box; padding: 0px 5px;">239</li></ul>







0 0
原创粉丝点击