libhv之hloop源码分析

1int hloop_run(hloop_t* loop)

hloop_run总结
1.loop状态判断和管理
2.loop的flags管理(HLOOP_FLAG_QUIT_WHEN_NO_ACTIVE_EVENTS,HLOOP_FLAG_RUN_ONCE,HLOOP_FLAG_AUTO_FREE
3.创建custom event通信fd,方便loop进行custom event事件传递(线程安全,属于IO事件)
4.hloop_process_events真正处理事件的函数

int hloop_run(hloop_t* loop) {
	//状态控制已经状态判断,loop基于单线程运行模式,所以状态无锁
    if (loop == NULL) return -1;
    if (loop->status == HLOOP_STATUS_RUNNING) return -2;

    loop->status = HLOOP_STATUS_RUNNING;
    loop->pid = hv_getpid();
    loop->tid = hv_gettid();
    
	//用户custom event通信,即pairsocket,属于IO事件
    if (loop->intern_nevents == 0) {
        hmutex_lock(&loop->custom_events_mutex);
        if (loop->eventfds[EVENTFDS_WRITE_INDEX] == -1) {
            hloop_create_eventfds(loop);
        }
        hmutex_unlock(&loop->custom_events_mutex);

#ifdef DEBUG
        htimer_add(loop, hloop_stat_timer_cb, HLOOP_STAT_TIMEOUT, INFINITE);
        ++loop->intern_nevents;
#endif
    }

    while (loop->status != HLOOP_STATUS_STOP) {
        if (loop->status == HLOOP_STATUS_PAUSE) {
            hv_msleep(HLOOP_PAUSE_TIME);
            hloop_update_time(loop);
            continue;
        }
        ++loop->loop_cnt;
        
        //hloop标志,参考epool的flag
        //当没有激活事件的时候,退出loop
        if ((loop->flags & HLOOP_FLAG_QUIT_WHEN_NO_ACTIVE_EVENTS) &&
            loop->nactives <= loop->intern_nevents) {
            break;
        }
		
		//真正处理事件的函数
        hloop_process_events(loop, HLOOP_MAX_BLOCK_TIME);
		
		//只运行一次,然后退出loop
        if (loop->flags & HLOOP_FLAG_RUN_ONCE) {
            break;
        }
    }

    loop->status = HLOOP_STATUS_STOP;
    loop->end_hrtime = gethrtime_us();
	
	//自动释放loop
    if (loop->flags & HLOOP_FLAG_AUTO_FREE) {
        hloop_cleanup(loop);
        HV_FREE(loop);
    }
    return 0;
}
2.int hloop_process_events(hloop_t* loop, int timeout_ms)

hloop_process_events总结

  1. 处理事件优先级:timer > io > idle
  2. 如果有timer事件并且timeout,则加入pendding队列,并且立马处理timer事件,跳过io事件
  3. 如果存在io并且没有触发timer的情况下,则检查io状态,如果io事件触发则加入pendding队列
  4. custom 属于io事件
  5. 当不存在pendding事件,则触发idle
  6. 真正处理事件的是hloop_process_pendings
int hloop_process_events(hloop_t* loop, int timeout_ms) {
    // ios -> timers -> idles
    int nios, ntimers, nidles;
    nios = ntimers = nidles = 0;

    // calc blocktime
    int32_t blocktime_ms = timeout_ms;
    //如果存在定时器,则检查定时器是否超时,
    //由于这里是基于小根堆实现的定时器,所以只需要检查根节点是否超时即可
    if (loop->ntimers) {
        hloop_update_time(loop);
        int64_t blocktime_us = blocktime_ms * 1000;
        if (loop->timers.root) {
            int64_t min_timeout = TIMER_ENTRY(loop->timers.root)->next_timeout - loop->cur_hrtime;
            blocktime_us = MIN(blocktime_us, min_timeout);
        }
        if (loop->realtimers.root) {
            int64_t min_timeout = TIMER_ENTRY(loop->realtimers.root)->next_timeout - hloop_now_us(loop);
            blocktime_us = MIN(blocktime_us, min_timeout);
        }
		//如果已经超时,则说明定时器已经触发,直接处理定时器
        if (blocktime_us < 0) goto process_timers;
        blocktime_ms = blocktime_us / 1000 + 1;
        blocktime_ms = MIN(blocktime_ms, timeout_ms);
    }
	
	//如果存在io则处理iowatcher_poll_events,不同的模型,实现不一样
	//如果io事件被触发则加入pendding队列
    if (loop->nios) {
        nios = hloop_process_ios(loop, blocktime_ms);
    } else {
        hv_msleep(blocktime_ms);
    }
    hloop_update_time(loop);
    // wakeup by hloop_stop
    if (loop->status == HLOOP_STATUS_STOP) {
        return 0;
    }

process_timers:
	//处理定时器,并加入pendding队列,真正触发cb的是hloop_process_pendings
    if (loop->ntimers) {
        ntimers = hloop_process_timers(loop);
    }
	
	//如果不存pending事件,则触发idles事件
    int npendings = loop->npendings;
    if (npendings == 0) {
        if (loop->nidles) {
            nidles= hloop_process_idles(loop);
        }
    }
	//处理pendding事件
    int ncbs = hloop_process_pendings(loop);
    // printd("blocktime=%d nios=%d/%u ntimers=%d/%u nidles=%d/%u nactives=%d npendings=%d ncbs=%d\n",
    //         blocktime, nios, loop->nios, ntimers, loop->ntimers, nidles, loop->nidles,
    //         loop->nactives, npendings, ncbs);
    return ncbs;
}
3.int hloop_process_pendings(hloop_t* loop)

hloop_process_pendings总结

  1. 根据优先级遍历队列处理加入的pendding事件,如果存在回调则触发回调
int hloop_process_pendings(hloop_t* loop) {
    if (loop->npendings == 0) return 0;

    hevent_t* cur = NULL;
    hevent_t* next = NULL;
    int ncbs = 0;
    // NOTE: invoke event callback from high to low sorted by priority.
    //从高优先级遍历到低优先级,不同优先级的事件放在不同list
    for (int i = HEVENT_PRIORITY_SIZE-1; i >= 0; --i) {
        cur = loop->pendings[i];
        //遍历当前优先级下的所有事件,并且触发回调
        while (cur) {
            next = cur->pending_next;
            if (cur->pending) {
                if (cur->active && cur->cb) {
                    cur->cb(cur);
                    ++ncbs;
                }
                cur->pending = 0;
                // NOTE: Now we can safely delete event marked as destroy.
                if (cur->destroy) {
                    EVENT_DEL(cur);
                }
            }
            cur = next;
        }
        loop->pendings[i] = NULL;
    }
    loop->npendings = 0;
    return ncbs;
}

至此hloop_run的链路分析完毕。

总结
  1. timer,io均是无锁模式,所以不能跨线程使用loop的timer和io。
  2. custom event是线程安全的,所以可以跨线程使用,即:hloop_post_event
  3. 如果想跨线程使用timer和io可以通过hloop_post_event传递使用,可参考tinyhttpd.c
  4. custom event属于IO事件(hloop_create_eventfds
    在这里插入图片描述
问题:如果loop基于单线程模式,那么如果作为服务端是怎么实现高并发的呢?

答:多线程模型原理可以参考EventLoopThreadPool。多线程demo可以参考libhv:examples/multi-thread 给出的几种常见的多线程/多进程模式的具体写法:

  • multi-acceptor-processes:多accept进程模式
  • multi-acceptor-threads:多accept线程模式
  • one-acceptor-multi-workers:一个accept线程+多worker线程
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值