libhv之EventLoop源码分析

坚持一个原则:one loop--->one thread---->one io_watcher
事件优先级:timer > io > idle

EventLoop源码位置:evppEventLoop是C++版本的loop,对常用的loop功能进行基本封装,主要包括loop的状态、定时器、runInLoop等单线程模型的事件封装。稍后分析的TimerThread、TcpClient、TcpServer、UdpClient、UdpServer均是基于EventLoop实现的。

源码:EventLoop.h
//部分源码分析,Status 作为基类主要用作状态管理
class EventLoop : public Status {

 //run内部设置状态为kRunning,然后调用hloop_run进行阻塞调用
 //为了不阻塞主线程,应该单单独起线程运行run
 // @brief Run loop forever
    void run() {
        if (loop_ == NULL) return;
        if (status() == kRunning) return;
        ThreadLocalStorage::set(ThreadLocalStorage::EVENT_LOOP, this);
        setStatus(kRunning);
        hloop_run(loop_);
        setStatus(kStopped);
    }
}

	//判断是否在当前run的线程
 bool isInLoopThread() {
        if (loop_ == NULL) return false;
        return hv_gettid() == hloop_tid(loop_);
    }
    
 // 通过前面的源码分析,loop必须遵守单线程模式,如果需要在其他线程调用需要通过custom event来处理
 // 事件,即postEvent。  runInLoop对postEvent进行了封装,支持多线程调用。
 // 线程安全
 void runInLoop(Functor fn) {
        if (isRunning() && isInLoopThread()) {
            if (fn) fn();
        } else {
            queueInLoop(std::move(fn));
        }
    }
    

EventLoop总结:

  1. 需要单独起线程,运行run。否则会阻塞当前线程
  2. runInLoop封装了postEvent,支持多线程模式
  3. setTimer非线程安全(易误用)。外部应该调用:setTimerInLoop
源码:EventLoopThread.h
//部分源码,对EventLoop进一步封装,简化调用方式,run内部起线程
class EventLoopThread : public Status {

  // @param wait_thread_started: if ture this method will block until loop_thread started.
    // @param pre: This functor will be executed when loop_thread started.
    // @param post:This Functor will be executed when loop_thread stopped.
    void start(bool wait_thread_started = true,
               Functor pre = Functor(),
               Functor post = Functor()) {
        if (status() >= kStarting && status() < kStopped) return;
        setStatus(kStarting);
		//内部启线程,方便外部调用
        thread_ = std::make_shared<std::thread>(&EventLoopThread::loop_thread, this, pre, post);

        if (wait_thread_started) {
            while (loop_->status() < kRunning) {
                hv_delay(1);
            }
        }
    }
    
private:
    EventLoopPtr                 loop_;
    std::shared_ptr<std::thread> thread_;//内部loop工作线程
}

EventLoopThread总结:
1.使用简单,start即可,不会阻塞当前线程
2. EventLoopThread 属于单线程模式,性能不及高并发

源码:EventLoopThreadPool.h
class EventLoopThreadPool : public Status {
//负载均衡模型,根据不同的负责模型,返回合适的EventLoop
EventLoopPtr nextLoop(load_balance_e lb = LB_RoundRobin) {
        size_t numLoops = loop_threads_.size();
        if (numLoops == 0) return NULL;
        size_t idx = 0;
        if (lb == LB_RoundRobin) {
            if (++next_loop_idx_ >= numLoops) next_loop_idx_ = 0;
            idx = next_loop_idx_ % numLoops;
        } else if (lb == LB_Random) {
            idx = hv_rand(0, numLoops - 1);
        } else if (lb == LB_LeastConnections) {
            for (size_t i = 1; i < numLoops; ++i) {
                if (loop_threads_[i]->loop()->connectionNum < loop_threads_[idx]->loop()->connectionNum) {
                    idx = i;
                }
            }
        } else {
            // Not Implemented
        }
        return loop_threads_[idx]->loop();
    }
	
	//根据下标获取EventLoop,如果不指定则通过负载均衡模型来动态选择EventLoop
    EventLoopPtr loop(int idx = -1) {
        if (idx >= 0 && idx < (int)loop_threads_.size()) {
            return loop_threads_[idx]->loop();
        }
        return nextLoop();
    }

//启动指定数量的EventLoopThread,实现多线程模型
 void start(bool wait_threads_started = false,
               std::function<void(const EventLoopPtr&)> pre = NULL,
               std::function<void(const EventLoopPtr&)> post = NULL) {
        if (thread_num_ == 0) return;
        if (status() >= kStarting && status() < kStopped) return;
        setStatus(kStarting);

        auto started_cnt = std::make_shared<std::atomic<int>>(0);
        auto exited_cnt  = std::make_shared<std::atomic<int>>(0);

        loop_threads_.clear();
        for (int i = 0; i < thread_num_; ++i) {
            auto loop_thread = std::make_shared<EventLoopThread>();
            const EventLoopPtr& loop = loop_thread->loop();
            loop_thread->start(false,
                [this, started_cnt, pre, &loop]() {
                    if (++(*started_cnt) == thread_num_) {
                        setStatus(kRunning);
                    }
                    if (pre) pre(loop);
                    return 0;
                },
                [this, exited_cnt, post, &loop]() {
                    if (post) post(loop);
                    if (++(*exited_cnt) == thread_num_) {
                        setStatus(kStopped);
                    }
                    return 0;
                }
            );
            loop_threads_.push_back(loop_thread);
        }

        if (wait_threads_started) {
            while (status() < kRunning) {
                hv_delay(1);
            }
        }
    }

private:
    int                                         thread_num_;//工作线程数量
    std::vector<EventLoopThreadPtr>             loop_threads_;//EventLoopThread数组
    std::atomic<unsigned int>                   next_loop_idx_;//负载均衡
}

EventLoopThreadPool总结:
1.使用简单,支持多线程,支持高并发,支持负载均衡

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值