很多人解读libuv,每个人侧重点则不同,最近看了看libuv源码,从用户线程的调度过程来解读下libuv,以下解读如有不正确,也请指正(前提:从linux角度读libuv源码)
此处列举下面要解答的问题:
1,libuv在线程间传递消息采用的什么机制
2,libuv创建的工作线程会不会在执行完用户任务后退出
3,libuv从接收任务到将任务发送给工作线程,是怎么个实现过程
4,工作线程执行完毕后,调用的work done是如何被执行的
1,libuv把任务发送给用户工作线程时,使用的是条件变量通知
static void post(QUEUE* q, enum uv__work_kind kind) {
uv_mutex_lock(&mutex);
if (kind == UV__WORK_SLOW_IO) {
/* Insert into a separate queue. */
QUEUE_INSERT_TAIL(&slow_io_pending_wq, q);
if (!QUEUE_EMPTY(&run_slow_work_message)) {
/* Running slow I/O tasks is already scheduled => Nothing to do here.
The worker that runs said other task will schedule this one as well. */
uv_mutex_unlock(&mutex);
return;
}
q = &run_slow_work_message;
}
QUEUE_INSERT_TAIL(&wq, q); //将任务插入工作队列
if (idle_threads > 0)
uv_cond_signal(&cond); //此处即为给用户工作线程发送条件变量通知消息
uv_mutex_unlock(&mutex);
}
2,通常情况下,libuv创建的4个默认工作线程不会退出
3,libuv将任务发送给用户工作线程,用户工作线程通过条件变量唤醒,然后从工作队列中取出一个任务,并调用用户设定的实际处理函数,来处理具体业务
static void worker(void* arg) {
struct uv__work* w;
QUEUE* q;
int is_slow_work;
uv_sem_post((uv_sem_t*) arg); //通知主线程:工作线程已启动
arg = NULL;
uv_mutex_lock(&mutex);
for (;;) {
/* `mutex` should always be locked at this point. */
/* Keep waiting while either no work is present or only slow I/O
and we're at the threshold for that. */
while (QUEUE_EMPTY
libuv用户工作线程详解:线程间通信与调度

本文从用户线程调度的角度深入解析libuv,探讨其如何利用条件变量、工作队列及线程间通信机制进行任务处理。libuv通常创建4个工作线程,任务通过条件变量唤醒工作线程执行,完成后再通过uv_async_send()通知主loop执行work done。sem_post用于协调主loop与其他任务的执行顺序。
最低0.47元/天 解锁文章
1318

被折叠的 条评论
为什么被折叠?



