libuv学习笔记(18)
来源:互联网 发布:mac上pdf软件 编辑:程序博客网 时间:2024/05/16 18:43
libuv学习笔记(18)
uv_fs_poll_t数据结构与相关函数
数据结构
typedef struct uv_fs_poll_s uv_fs_poll_t;struct uv_fs_poll_s { UV_HANDLE_FIELDS//uv_handle_t成员 /* Private, don't touch. */ void* poll_ctx;};//内部数据结构struct poll_ctx { uv_fs_poll_t* parent_handle; /* NULL if parent has been stopped or closed */ int busy_polling; unsigned int interval; uint64_t start_time; uv_loop_t* loop; uv_fs_poll_cb poll_cb; uv_timer_t timer_handle;//定时器 uv_fs_t fs_req; /* TODO(bnoordhuis) mark fs_req internal */ uv_stat_t statbuf; char path[1]; /* variable length */};
相关函数
初始化
int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle) { //简单的初始化handle uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_POLL); return 0;}
开始监听
int uv_fs_poll_start(uv_fs_poll_t* handle, uv_fs_poll_cb cb, const char* path, unsigned int interval) { struct poll_ctx* ctx; uv_loop_t* loop; size_t len; int err; if (uv__is_active(handle)) return 0; loop = handle->loop; len = strlen(path); ctx = uv__calloc(1, sizeof(*ctx) + len);//分配内存,大小为结构体大小加上字符串长度 if (ctx == NULL) return UV_ENOMEM; ctx->loop = loop; ctx->poll_cb = cb; ctx->interval = interval ? interval : 1;//设置间隔 ctx->start_time = uv_now(loop);//记录起始时间 ctx->parent_handle = handle;//与uv_fs_poll_t联系起来 memcpy(ctx->path, path, len + 1);//路径 //初始化定时器 err = uv_timer_init(loop, &ctx->timer_handle); if (err < 0) goto error; ctx->timer_handle.flags |= UV__HANDLE_INTERNAL;//内部使用handle uv__handle_unref(&ctx->timer_handle); err = uv_fs_stat(loop, &ctx->fs_req, ctx->path, poll_cb); if (err < 0) goto error; handle->poll_ctx = ctx; uv__handle_start(handle); return 0;error: uv__free(ctx); return err;}
int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { int err; //初始化请求 uv_fs_req_init(loop, req, UV_FS_STAT, cb); err = fs__capture_path(req, path, NULL, cb != NULL); if (err) { return uv_translate_sys_error(err); } if (cb) { //QUEUE_FS_TP_JOB(loop, req);展开如下: do { uv__req_register(loop, req); //将uv__fs_work添加到线程池,uv__fs_work中会查询文件状态,uv__fs_done会调用poll_cb,其中会比较上一次与本次的文件状态,若状态改变会调用start的回调函数。poll_cb最终会再次开启定时器 uv__work_submit((loop), &(req)->work_req, uv__fs_work, uv__fs_done); } while (0) return 0; } else { fs__stat(req); return req->result; }}
停止监听
int uv_fs_poll_stop(uv_fs_poll_t* handle) { struct poll_ctx* ctx; if (!uv__is_active(handle)) return 0; ctx = handle->poll_ctx; assert(ctx != NULL); assert(ctx->parent_handle != NULL); ctx->parent_handle = NULL; handle->poll_ctx = NULL; //如果定时器为激活状态,那么关闭它 if (uv__is_active(&ctx->timer_handle)) uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb); uv__handle_stop(handle); return 0;}
整个文件状态轮询是通过线程池与定时器实现的
1.首先向线程池注册一个任务uv__fs_work,在这个任务中会查询对应文件的状态,结果保存在uv_fs_t的statbuf中。
2.uv__fs_work完成之后,会通过loop的wq_async向loop发送异步唤醒请求,此处通过uv_mutex_lock来达到线程同步
3.在loop所在线程中,处理唤醒请求,调用uv__fs_done
4.uv__fs_done最终调用poll_cb,在poll_cb中会判断上一次的文件状态(存在poll_ctx的statbuf中)与本次文件状态是否有区别,如果有区别,就会调用用户的回调函数,并将statbuf赋值给poll_ctx的statbuf。poll_cb最终会再次激活定时器
5.定时器的回调函数timer_cb会调用uv_fs_stat再次重复上面的流程
uv_fs_poll_t所用的定时器是没有设置重复间隔的,所以只会执行一次,每次执行完之后,会再次激活。
只有uv__fs_work函数也就是查询文件状态的函数会在线程池中执行,其他的回调函数都在loop所在的线程池中执行,以此来达到线程池安全。
0 0
- libuv学习笔记(18)
- libuv学习笔记(2)
- libuv学习笔记(3)
- libuv学习笔记(4)
- libuv学习笔记(5)
- libuv学习笔记(6)
- libuv学习笔记(7)
- libuv学习笔记(9)
- libuv学习笔记(10)
- libuv学习笔记(11)
- libuv学习笔记(12)
- libuv学习笔记(13)
- libuv学习笔记(14)
- libuv学习笔记(16)
- libuv学习笔记(17)
- libuv学习笔记(20)
- libuv学习笔记(21)
- libuv学习笔记(22)
- Java基础之(一) 变量
- zookeeper轻松入门
- wait notify notifyAll
- Program4_F
- leetcode 88 Merge Sorted Array
- libuv学习笔记(18)
- ThreadPoolExecutor原理与使用
- java获取项目访问路径的方法
- APP开发实战66-功能级别的BaseActivity设计
- 关于eclipse下连接安卓手机
- 235. Lowest Common Ancestor of a Binary Search Tree
- Java/Android中的DES加密
- [Leetcode]92. Reverse Linked List II
- MAVEN的安装和Myeclipse+maven的配置和使用