回调虚函数

时间:2017-09-22 02:40:26

标签: c++ multithreading callback

我正在使用嵌入式平台上的线程做一些工作。这个平台提供了一个Thread类,它有一个start方法,它接受一个函数指针,如下所示:

void do_in_parallel() {
    // Some stuff to do in a new thread
}

Thread my_thread;
my_thread.start(do_in_parallel);

问题是无法传递参数。 1 我想通过创建一个抽象类来解决这个问题,将其称为Thread2,扩展Thread(或者它可以只有Thread作为实例数据)。

Thread2将有一个纯虚函数void run(),目标是将其传递给Thread::start(void*()),除了我很快就知道成员函数指针有不同的类型,不能像这样用过。我可以使run()静态,但是我仍然不能有多个实例,打败了整个目的(更不用说你不能拥有虚拟静态函数)。

是否存在任何不涉及更改原始Thread类的变通方法(考虑到它是一个我原来坚持使用的库)?

<子> 1。在许多情况下,全局变量是一种可用的解决方法,除非从同一函数指针实例化多个线程。在这种情况下,我无法想出一种避免竞争条件的方法。

3 个答案:

答案 0 :(得分:6)

编写一个全局线程池。

它维护一个任务队列。这些任务可以有状态。

当您向队列添加任务时,您可以选择同时请求它立即获取线程。或者你可以等待池中的线程完成他们正在做的事情。

池中的线程由提供的Thread类创建,它们从池中获取其行进指令。在大多数情况下,他们应该弹出任务,执行它们,然后等待另一个准备好的任务。

如果不允许等待,您仍然可以拥有一些存储线程状态的全局线程管理器。

池/管理器返回相当于future<T>的等效内容,增加了您想要的任何功能。提供任务的代码通过该对象而不是嵌入的Thread类型与任务交互。

答案 1 :(得分:3)

如果允许锁定,可以编写一个简单的包装器

void start(Thread& t, void (*fn)(void*), void* p)
{
    static std::mutex mtx;  // or any other mutex
    static void* sp;
    static void (*sfn)(void*);

    mtx.lock();
    sp = p;
    sfn = fn;

    t.start([]{
        auto p = sp;
        auto fn = sfn;
        mtx.unlock();
        fn(p);
    });
}

这显然不会很好地扩展,所有的线程创建都经历了相同的锁定,但它可能已经足够了。

请注意,这是例外 - un 安全,但我认为这在嵌入式系统中很好。

包装器就位

template<typename C>
void start(Thread& t, C& c)
{
    start(t, [](void* p){
        (*(C*)p)();
    }, &c);
}

允许使用任何可调用对象。这个特定的实现将管理可调用生命周期的责任放在调用者身上。

答案 2 :(得分:0)

您可以创建自己的线程调度机制(生产者 - 消费者队列),该机制围绕特定于平台的线程构建。 我假设您为目标平台提供了mutexconditional variables / signalling mechanism的等效设施。

  • 创建一个可以接受函数对象的线程安全队列。
  • run方法创建一个线程并等待队列。
  • 调用线程可以调用post()/invoke()方法,只需将一个函数对象插入队列。
  • 函数对象可以将必要的参数传递给调用者线程。