【发布时间】:2017-06-05 02:31:32
【问题描述】:
我想实现一个小型线程包装器,它提供线程是否仍处于活动状态或线程是否已完成其工作的信息。为此,我需要将要由线程类执行的函数及其参数传递给另一个函数。我有一个简单的实现应该可以工作,但无法编译,我不知道该怎么做才能让它工作。
这是我的代码:
#include <unistd.h>
#include <iomanip>
#include <iostream>
#include <thread>
#include <utility>
class ManagedThread
{
public:
template< class Function, class... Args> explicit ManagedThread( Function&& f, Args&&... args);
bool isActive() const { return mActive; }
private:
volatile bool mActive;
std::thread mThread;
};
template< class Function, class... Args>
void threadFunction( volatile bool& active_flag, Function&& f, Args&&... args)
{
active_flag = true;
f( args...);
active_flag = false;
}
template< class Function, class... Args>
ManagedThread::ManagedThread( Function&& f, Args&&... args):
mActive( false),
mThread( threadFunction< Function, Args...>, std::ref( mActive), f, args...)
{
}
static void func() { std::cout << "thread 1" << std::endl; }
int main() {
ManagedThread mt1( func);
std::cout << "thread 1 active = " << std::boolalpha << mt1.isActive() << std::endl;
::sleep( 1);
std::cout << "thread 1 active = " << std::boolalpha << mt1.isActive() << std::endl;
return 0;
}
我得到的编译器错误:
In file included from /usr/include/c++/5/thread:39:0,
from prog.cpp:4:
/usr/include/c++/5/functional: In instantiation of 'struct std::_Bind_simple<void (*(std::reference_wrapper<volatile bool>, void (*)()))(volatile bool&, void (&)())>':
/usr/include/c++/5/thread:137:59: required from 'std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(volatile bool&, void (&)()); _Args = {std::reference_wrapper<volatile bool>, void (&)()}]'
prog.cpp:28:82: required from 'ManagedThread::ManagedThread(Function&&, Args&& ...) [with Function = void (&)(); Args = {}]'
prog.cpp:35:28: required from here
/usr/include/c++/5/functional:1505:61: error: no type named 'type' in 'class std::result_of<void (*(std::reference_wrapper<volatile bool>, void (*)()))(volatile bool&, void (&)())>'
typedef typename result_of<_Callable(_Args...)>::type result_type;
^
/usr/include/c++/5/functional:1526:9: error: no type named 'type' in 'class std::result_of<void (*(std::reference_wrapper<volatile bool>, void (*)()))(volatile bool&, void (&)())>'
_M_invoke(_Index_tuple<_Indices...>)
^
现场示例可在此处获得:https://ideone.com/jhBF1q
【问题讨论】:
-
我在转发参数方面没有太多经验,但我只是觉得你错过了一个或两个
std::forward电话......你可能想阅读"When to use std::forward to forward arguments?"。跨度> -
另请注意,您可能无法获得预期的结果。您创建的线程可能会在您第一次调用
mt1.isActive()之前启动、运行和完成。考虑在线程函数中添加一个短暂的睡眠,然后在main函数中添加一个更长的睡眠。 -
我也这么认为,但我添加的每个 std::forward 调用实际上都让情况变得更糟,即导致更多的编译器错误。也许如果当前问题得到解决,我将需要(并且能够)在我的函数中应用 std::forward 调用,但首先我需要让线程构造函数调用工作。
-
关于时机:你是对的,但这不是一个真正的问题。重要的是在线程完成后获取
isActive() == false信息。 -
最后,关于您的设计的另一个小想法:为什么不让
threadFunction成为包装器的member 函数?那么你不需要将mActive标志作为参数传递给函数。