ril.cpp中watch_table,timer_list和pending_list的分析

来源:互联网 发布:java 日历选择控件 编辑:程序博客网 时间:2024/06/08 20:15

在ril.cpp中定义了3个队列,分别是watch_table,timer_list和pending_list,他们里面都存放的是ril_event结构,他们的主要作用如下:

1. watch_table是一个指针数组,它里面存放的是靠多路复用来驱动的ril_event,起作用的是fd参数,使用ril_event_add朝里面添加event,使用ril_event_del来删除里面的event。

2. timer_list里面存放的是靠timer来驱动的event列表,使用ril_timer_add朝里面添加event。只有一个函数会调用ril_timer_add把event添加进来,那就是internalRequestTimedCallback这个函数,该函数又由RIL_requestTimedCallback来调用。在ril_event_loop里面,select多路复用的timeout时间就是当前timer_list里面最近一个将要超时的event的超时时间。

3. pending_list,是一个存储即将被执行的ril_event的列表(所谓即将执行,就是调用该event的callback函数),下面两个情况会把event添加到该列表:a: watch_table里面某一个event的fd里面有数据可读; b. timer_list里面某一个event已经timeout了。


void ril_event_loop(){    int n;    fd_set rfds;    struct timeval tv;    struct timeval * ptv;    for (;;) {        /* make local copy of read fd_setreadFds里面的fd都是watch_table里面的event的fd*/        memcpy(&rfds, &readFds, sizeof(fd_set));/*计算select需要等待的时间,这个值是从timer_list里面的event计算出来的*/        if (-1 == calcNextTimeout(&tv)) {            // no pending timers; block indefinitely            dlog("~~~~ no timers; blocking indefinitely ~~~~");            ptv = NULL;        } else {            dlog("~~~~ blocking for %ds + %dus ~~~~", (int)tv.tv_sec, (int)tv.tv_usec);            ptv = &tv;        }/*多路复用,等待有数据可读,或者超时*/        n = select(nfds, &rfds, NULL, NULL, ptv);        dlog("~~~~ %d events fired ~~~~", n);        if (n < 0) {            if (errno == EINTR) continue;            LOGE("ril_event: select error (%d)", errno);            // bail?            return;        }        /* Check for timeoutstimer_event里面有event超时了,需要调用超时event的callback来执行相关操作,把这些event加入到pending_list里面*/        processTimeouts();        /* Check for read-ready处理watch_table里面的有数据可读的fd所在的event,将其放入到timer_list里面*/        processReadReadies(&rfds, n);        /* Fire away执行pending_list里面的event*/        firePending();    }}


/*取得最近马上要超时的一个event的超时时间离现在的微秒数,因为在timer_event列表里面的event都是按照时间排序排列好的,所以我们只判断最前面一个event就行了。返回的这个值就是ril_event_loop函数里面select的超时时间*/static int calcNextTimeout(struct timeval * tv){    struct ril_event * tev = timer_list.next;    struct timeval now;    getNow(&now);    // Sorted list, so calc based on first node    if (tev == &timer_list) {        // no pending timers        return -1;    }    dlog("~~~~ now = %ds + %dus ~~~~", (int)now.tv_sec, (int)now.tv_usec);    dlog("~~~~ next = %ds + %dus ~~~~",            (int)tev->timeout.tv_sec, (int)tev->timeout.tv_usec);    if (timercmp(&tev->timeout, &now, >)) {        timersub(&tev->timeout, &now, tv);    } else {        // timer already expired.        tv->tv_sec = tv->tv_usec = 0;    }    return 0;}


原创粉丝点击