实现signal和slot机制(2)-跨线程投递

本文介绍了如何实现跨线程的信号槽机制,通过对象线程绑定,将slot调用打包成Task并放入事件循环中执行。文章详细阐述了Task的创建、事件循环与对象绑定、任务投递的实现方式,并给出了运用实例,展示了在不同线程上下文中信号槽的正确执行。虽然存在线程安全问题,但依然证明了机制的有效性。
摘要由CSDN通过智能技术生成

前言

在1中,我们实现了一个基础的signal+slot的模块件调用机制,不过那个direct调用,在这篇中,我们将支持夸线程调用,即在对象的线程上下文中,调用对象的函数。

对象线程绑定

在qt中,有一个很重要的概念,对象线程绑定,即在每个对象实例时候,其保存其线程上下文信息,其中就有一个事件循环,跨线程的信号就是将这个一个task丢到这个事件循环中,在对象绑定的线程中完成slot响应。

实现

对slot调用的打包-Task

我们需要将一个跨线程的slot调用打包成一个task,然后丢到想相应的事件循环中。在事件循环中需要维护一个task队列,那第一还是需要做容器。

struct TaskBase
{
    virtual ~TaskBase() = 0;
    virtual void run() = 0;
};

TaskBase::~TaskBase()
{
}

TaskBase为我们Task基类,在事件循环中,维护其一个链表。
我们继承它,实现我们第一个Task,一个一般的Task。

template <typename Method>
struct NormalTask : public TaskBase
{
    typedef typename ParameterTupleTraits<ParameterTraits<Method>>::Parameters Parameters;
    typedef typename TypeTraits<typename ParameterTraits<Method>::classType_value>::pointerType_value type_value;

    NormalTask(type_value object, Method m, Parameters paras) : TaskBase(),
                                                                m_object(object),
                                                                m_method(m),
                                                                m_paras(paras)
    {
    }

    virtual ~NormalTask() {}

    void run()
    {
        printf("run:%lu\n", pthread_self());
        impleDoTask(m_object, m_method, m_paras);
    }

    type_value m_object;
    Method m_method;
    Parameters m_paras;
};

其实一个模板,于具体的对象成员函数相关,接受,对象指针,对象成员函数指针和参数。pthread_self可以打印当前线程的标识,其实一个unsigned long类型的数,这里为了看其的执行线程。

事件循环和对象绑定

为了实现对象线程绑定,我们必须提供一个在这套系统上的基类,正如qt中的QObject。

struct Box
{
    Box()
    {
        m_loop = EventLoop::currentEventLoop();
    }

    EventLoop *m_loop;
};

下面开始我们的事件循环,其实这只有一个任务队列,实际中其还必须能够监听系统各种事件,比如按键,鼠标,加其发送给合适的对象,就是我的一篇博客介绍的事件监听分发,这里不做讨论。

 static EventLoop *currentEventLoop()
    {
        EventLoop *re = NULL;
        pthread_t pid = pthread_self();
        std::map<pthread_t, EventLoop *>::iterator ite = s_eventloops.find(pid);
        if (ite != s_eventloops.end())
        {
            re = ite->second;
        }
        else
        {
            re = new EventLoop(pid);
            s_eventloops.insert(std::pair<pthread_t, EventLoop *>(pid, re));
        }
        return re;
    }

    static void exit()
    {
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值