libuv学习笔记(6)

libuv学习笔记(6)

uv_prepare_t、uv_idel_t、uv_check_t的数据结构与相关API

三种监视器(watcher),每次循环迭代都会调用它的回调函数

数据结构

typedef struct uv_prepare_s uv_prepare_t;
typedef struct uv_check_s uv_check_t;
typedef struct uv_idle_s uv_idle_t;
struct uv_prepare_s 
{
  UV_HANDLE_FIELDS//uv_handle_t的数据,此处不再展开,请参考之前的内容
  //UV_PREPARE_PRIVATE_FIELDS展开如下:
  uv_prepare_t* prepare_prev;//指向上一个
  uv_prepare_t* prepare_next;//指向下一个
  uv_prepare_cb prepare_cb;//回调函数
};

三种watcher的结构基本一致,只是其中的指针类型以及回调函数类型不同

相关API (以uv_prepare_t的相关函数为例,另外两种的处理函数流程基本一致)

1.初始化函数,导出函数,在uv.h中声明,loop-watcher.c中通过宏定义

基本的handle初始化流程,没有什么特殊的处理。

int uv_prepare_init(uv_loop_t* loop, uv_prepare_t* handle) 
{              
    //uv__handle_init(loop, (uv_handle_t*) handle, UV_PREPARE);展开:
    do {                                                                      
      (h)->loop = (loop);                                                    
      (h)->type = (UV_PREPARE);                                                     
      (h)->flags = UV__HANDLE_REF;  /* 设为引用状态. */    
      //将handle添加到loop的handle队列         
      QUEUE_INSERT_TAIL(&(loop)->handle_queue, &(handle)->handle_queue);            
      //uv__handle_platform_init(h);  展开
      ((handle)->u.fd = -1);                                           
    }                                                                           
    while (0)                                                    
    return 0;                                                                 
}      
2.开始(激活),导出函数,在uv.h中声明,loop-watcher.c中通过宏定义
int uv_prepare_start(uv_prepare_t* handle, uv_prepare_cb cb) 
{          
    uv_loop_t* loop = handle->loop;                                         
    uv_prepare_t* old_head;                                                 

    assert(handle->type == UV_PREPARE);                                     
    //如果已经是激活状态,直接返回                                                                      
    if (uv__is_active(handle))                                            
      return 0;                                                           
    //没有设置回调函数,返回错误                                                                      
    if (cb == NULL)                                                      
      return UV_EINVAL;                                                      

    //将本handle插入到loop的prepare_handles列表的表头                                                                        
    old_head = loop->prepare_handles;                                                                                                                
    handle->prepare_next = old_head;                                           
    handle->prepare_prev = NULL;                                               

    if (old_head) 
    {                                                           
      old_head->prepare_prev = handle;                                         
    }                                                                         

    loop->prepare_handles = handle;                                            

    handle->prepare_cb = cb;                                                   
    //uv__handle_start(handle);    展开如下
    do {                                                                       
      assert(((handle)->flags & UV__HANDLE_CLOSING) == 0);                        
      if (((handle)->flags & UV__HANDLE_ACTIVE) != 0) break;                         
      (handle)->flags |= UV__HANDLE_ACTIVE;//设为active状态                   
      //如果同时处于引用状态,loop的活动handle计数加一                       
      if (((handle)->flags & UV__HANDLE_REF) != 0) uv__active_handle_add(handle);        
    }                                                                           
    while (0);                                                                             
    return 0;                                                                 
  }    
3.停止handle,导出函数,在uv.h中声明,loop-watcher.c中通过宏定义
 int uv_prepare_stop(uv_prepare_t* handle) 
 {                              
    uv_loop_t* loop = handle->loop;                                                                                                        
    assert(handle->type == UV_PREPARE);                                        

    if (!uv__is_active(handle))                                               
      return 0;                                                               

    /* 如果本handle为loop  prepare_handle列表的第一个元素,更新loop的prepare_handles指针 */                                          
    if (loop->prepare_handles == handle) {                                     
      loop->prepare_handles = handle->prepare_next;                             
    }                                                                        

    /* 如果loop的下一个prepare_handle是本handle,更新 */                          
    if (loop->next_prepare_handle == handle) {                               
      loop->next_prepare_handle = handle->prepare_next;                       
    }                                                                         
    //从列表中删除本handle                                                                          
    if (handle->prepare_prev) {                                                
      handle->prepare_prev->prepare_next = handle->prepare_next;                 
    }                                                                         
    if (handle->prepare_next) {                                                
      handle->prepare_next->prepare_prev = handle->prepare_prev;                 
    }                                                                         

    //uv__handle_stop(handle); 展开如下:
    do {                                                                        
      assert(((h)->flags & UV__HANDLE_CLOSING) == 0);                           
      if (((h)->flags & UV__HANDLE_ACTIVE) == 0) break;                        
      (h)->flags &= ~UV__HANDLE_ACTIVE;//去掉active标志                 
      //如果同时在引用状态,loop的活动handle计数减一                        
      if (((h)->flags & UV__HANDLE_REF) != 0) uv__active_handle_rm(h);          
    }                                                                          
    while (0);                                                                       
    return 0;                                                                 
  }         
关闭操作(通过uv_close)

在uv_close中处理如下

...
case UV_PREPARE:
      uv_prepare_stop((uv_prepare_t*)handle);
      uv__handle_closing(handle);
      uv_want_endgame(loop, handle);
      return;
...

通过uv_want_endgame将handle插入到loop->endgame_handles的列表头,接着在uv_run中会调用uv_process_endgames处理所有的需要关闭的handle

...
      case UV_PREPARE:
      case UV_CHECK:
      case UV_IDLE:
        uv_loop_watcher_endgame(loop, handle);
        break;
...

通过代码可知,三种监视器的关闭都是调用的uv_loop_watcher_endgame:

void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) 
{
  if (handle->flags & UV__HANDLE_CLOSING) 
  {
    assert(!(handle->flags & UV_HANDLE_CLOSED));
    handle->flags |= UV_HANDLE_CLOSED;//状态变为UV__HANDLE_CLOSED
    //uv__handle_close(handle);展开如下:
    do {                                                                  
      QUEUE_REMOVE(&(handle)->handle_queue);//从队列中移除                              
      uv__active_handle_rm((uv_handle_t*) (handle));//handle计数递减      
      (handle)->flags |= UV_HANDLE_CLOSED;                                
      //调用回调函数                              
      if ((handle)->close_cb)                                             
        (handle)->close_cb((uv_handle_t*) (handle));                      
    } while (0)
  }
}
4.循环迭代中的调用(uv_run)
void uv_prepare_invoke(uv_loop_t* loop) {                                  
    uv_prepare_t* handle;                                                    

    (loop)->next_prepare_handle = (loop)->prepare_handles;                    
    //循环调用每一个uv_prepare_t的回调函数                                                                         
    while ((loop)->next_prepare_handle != NULL) {                            
      handle = (loop)->next_prepare_handle;                                  
      (loop)->next_prepare_handle = handle->prepare_next;                     

      handle->prepare_cb(handle);                                              
    }                                                                         
  }

三种watcher的结构以及处理流程基本都一致,相关函数都是通过loop-watcher.c中的UV_LOOP_WATCHER_DEFINE宏定义的。三种watcher的区别在于:
1.在循环迭代中的调用顺序不同:
idle(空转)在处理完上个迭代获取的请求之后调用
prepare紧接着idle之后调用
check在轮询之后调用

2.idle会影响loop i/o轮询的超时设置,当有idle时,超时时间为0。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值