我正在使用嵌入式平台上的线程做一些工作。这个平台提供了一个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。在许多情况下,全局变量是一种可用的解决方法,除非从同一函数指针实例化多个线程。在这种情况下,我无法想出一种避免竞争条件的方法。
答案 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)
您可以创建自己的线程调度机制(生产者 - 消费者队列),该机制围绕特定于平台的线程构建。
我假设您为目标平台提供了mutex
和conditional variables
/ signalling mechanism
的等效设施。
post()/invoke()
方法,只需将一个函数对象插入队列。