重写muduo网络库:eventfd和__thread的应用

eventfd和__thread的应用

muduo可以通过设置线程数量来决定开几个EventLoop,一个EventLoop有多个channel。当channel上有事件发生时,就应该在他所属的EventLoop上执行。
比如在一个mainReactor一个subReactor的情况下,mainReactor监听到一个新连接,要把这个新连接派发给subReactor。而subReactor可能大部分的时间都在loop(epoll_wait)阻塞的状态,mainReactor不能强把这个新连接塞给subReactor的Poller,这不合理也不安全,这就需要唤醒阻塞的subReactor,并且让它自己来把这个新连接添加到它的Poller上。
如何确定这个新连接是在它所属的EventLoop上处理的呢?
one loop per thread,我们可以通过系统中唯一的线程ID来确认他们所属的loop。

eventfd唤醒subReactor

在这里插入图片描述
eventfd用于创建一个专门唤醒事件的一个文件描述符。
当有新连接到来时,如果subReactor还在阻塞,不能一直等到subReactor阻塞返回,应该把它唤醒,立刻处理新连接。
我们可以让subReactor监听一个eventfd,在需要唤醒时往eventfd里写一个字节,这样subReactor就可以从loop(epoll_wait)阻塞状态返回了。
用传统的pipe也可以实现,但eventfd可以更高效的唤醒,因为他不必管理缓冲区。

巧用__thread关键字

__thread是GCC内置的线程局部存储设施(thread local storage)。可以用来修饰POD类型,不能修饰class类型,因为无法自动调用构造和析构函数。
__thread可以用于修饰全局变量、函数内的静态变量,但是不能用于修饰函数的局部变量会在class的普通成员变量。另外,__thread变量的初始化只能用编译期常量。例如:

__thread string t_obj1("hello");   //错误,不能调用对象的构造函数
__thread string* t_obj2 = new string;	//错误,初始化必须用编译器常量
__thread string* t_obj3 = NULL;		//正确,但是需要手工初始化并销毁对象

__thread修饰的变量每个线程都有一份独立实体,各个线程的变量值互不干扰。

获取当前线程id接口:
CurrentThread.h

#pragma once 

#include <unistd.h>
#include <sys/syscall.h>

namespace CurrentThread
{
    extern __thread int t_cachedTid;

    void cacheTid();

    inline int tid()
    {
        if(__builtin_expect(t_cachedTid == 0, 0))
        {
            cacheTid();
        }
        return t_cachedTid;
    }

}

CurrentThread.cc

#include "CurrentThread.h"

namespace CurrentThread
{
    __thread int t_cachedTid = 0;

    void cacheTid()
    {
        if(t_cachedTid == 0)
        {
            //通过Linux系统调用,获取当前线程的pid值
            t_cachedTid = static_cast<pid_t>(::syscall(SYS_gettid));
        }
    }
}

因为每个线程都有__thread修饰变量的一份独立实体,在线程调用CurrentThread::tid,获取的一定是当前线程的id。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_200_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值