如何正确扩展 std::thread 来包装生成的线程
How to properly extend std::thread to wrap spawned thread
我试图创建一个简单的包装器,供我的应用程序在 std::thread 中创建线程时使用。 使用此应用线程包装器的唯一目的是确保在每个生成的线程上一致地调用某些代码。 我认为这将是微不足道的,但是 std::thread 构造函数和参数传递相当复杂,我在这里遇到了非常神秘的构建错误。
这是我正在尝试执行的操作的简单示例:
#include <thread>
class AppThread : public std::thread
{
template< class Function, class... Args >
static void wrap( Function&& f, Args&&... args )
{
//Some code
f( std::forward<Args>( args )... );
}
public:
template< class Function, class... Args >
explicit AppThread( Function&& f, Args&&... args ) : std::thread( AppThread::wrap<Function,Args...>,
std::forward<Function>( f ), std::forward<Args>( args )... )
{}
};
void runA() {}
void runB( int x ) {}
main()
{
AppThread thread1 = AppThread( runA );
//AppThread thread2 = AppThread( runB, 5 );
}
我希望能够在使用 std:thread 的任何地方放入 AppThread,因此扩展和覆盖构造函数似乎是最好的方法。 但是将这些参数传递给我的包装方法会导致一连串错误(gcc 7.2)
In file included from thread_wrap.cpp:1:0:
gcc-7.2.0/include/c++/7.2.0/thread: In instantiation of ‘struct std::thread::_Invoker<std::tuple<void (*)(void (&)()), void (*)()> >’:
gcc-7.2.0/include/c++/7.2.0/thread:127:22: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(void (&)()); _Args = {void (&)()}]’
thread_wrap.cpp:15:130: required from ‘AppThread::AppThread(Function&&, Args&& ...) [with Function = void (&)(); Args = {}]’
thread_wrap.cpp:24:41: required from here
gcc-7.2.0/include/c++/7.2.0/thread:240:2: error: no matching function for call to ‘std::thread::_Invoker<std::tuple<void (*)(void (&)()), void (*)()> >::_M_invoke(std::thread::_Invoker<std::tuple<void (*)(void (&)()), void (*)()> >::_Indices)’
operator()()
^~~~~~~~
gcc-7.2.0/include/c++/7.2.0/thread:231:4: note: candidate: template<long unsigned int ..._Ind> decltype (std::__invoke((_S_declval<_Ind>)()...)) std::thread::_Invoker<_Tuple>::_M_invoke(std::_Index_tuple<_Ind ...>) [with long unsigned int ..._Ind = {_Ind ...}; _Tuple = std::tuple<void (*)(void (&)()), void (*)()>]
_M_invoke(_Index_tuple<_Ind...>)
^~~~~~~~~
gcc-7.2.0/include/c++/7.2.0/thread:231:4: note: template argument deduction/substitution failed:
gcc-7.2.0/include/c++/7.2.0/thread: In substitution of ‘template<long unsigned int ..._Ind> decltype (std::__invoke(_S_declval<_Ind>()...)) std::thread::_Invoker<std::tuple<void (*)(void (&)()), void (*)()> >::_M_invoke<_Ind ...>(std::_Index_tuple<_Ind1 ...>) [with long unsigned int ..._Ind = {0, 1}]’:
gcc-7.2.0/include/c++/7.2.0/thread:240:2: required from ‘struct std::thread::_Invoker<std::tuple<void (*)(void (&)()), void (*)()> >’
gcc-7.2.0/include/c++/7.2.0/thread:127:22: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(void (&)()); _Args = {void (&)()}]’
thread_wrap.cpp:15:130: required from ‘AppThread::AppThread(Function&&, Args&& ...) [with Function = void (&)(); Args = {}]’
thread_wrap.cpp:24:41: required from here
gcc-7.2.0/include/c++/7.2.0/thread:233:29: error: no matching function for call to ‘__invoke(std::__tuple_element_t<0, std::tuple<void (*)(void (&)()), void (*)()> >, std::__tuple_element_t<1, std::tuple<void (*)(void (&)()), void (*)()> >)’
-> decltype(std::__invoke(_S_declval<_Ind>()...))
~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
In file included from gcc-7.2.0/include/c++/7.2.0/tuple:41:0,
from gcc-7.2.0/include/c++/7.2.0/bits/unique_ptr.h:37,
from gcc-7.2.0/include/c++/7.2.0/memory:80,
from gcc-7.2.0/include/c++/7.2.0/thread:39,
from thread_wrap.cpp:1:
gcc-7.2.0/include/c++/7.2.0/bits/invoke.h:89:5: note: candidate: template<class _Callable, class ... _Args> constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&& ...)
__invoke(_Callable&& __fn, _Args&&... __args)
^~~~~~~~
gcc-7.2.0/include/c++/7.2.0/bits/invoke.h:89:5: note: template argument deduction/substitution failed:
gcc-7.2.0/include/c++/7.2.0/bits/invoke.h: In substitution of ‘template<class _Callable, class ... _Args> constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&& ...) [with _Callable = void (*)(void (&)()); _Args = {void (*)()}]’:
gcc-7.2.0/include/c++/7.2.0/thread:233:29: required by substitution of ‘template<long unsigned int ..._Ind> decltype (std::__invoke(_S_declval<_Ind>()...)) std::thread::_Invoker<std::tuple<void (*)(void (&)()), void (*)()> >::_M_invoke<_Ind ...>(std::_Index_tuple<_Ind1 ...>) [with long unsigned int ..._Ind = {0, 1}]’
gcc-7.2.0/include/c++/7.2.0/thread:240:2: required from ‘struct std::thread::_Invoker<std::tuple<void (*)(void (&)()), void (*)()> >’
gcc-7.2.0/include/c++/7.2.0/thread:127:22: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(void (&)()); _Args = {void (&)()}]’
thread_wrap.cpp:15:130: required from ‘AppThread::AppThread(Function&&, Args&& ...) [with Function = void (&)(); Args = {}]’
thread_wrap.cpp:24:41: required from here
gcc-7.2.0/include/c++/7.2.0/bits/invoke.h:89:5: error: no type named ‘type’ in ‘struct std::__invoke_result<void (*)(void (&)()), void (*)()>’
绝对可以在这里使用一些见解! 谢谢
这是我认为山姆正在开车的一个例子。 如您所见,它只有几行代码,所以我就不说了。
#include <iostream>
#include <thread>
#include <functional>
void preamble (void) { std::cout << "preamblen"; }
template <class F, class ... Args> std::thread ThreadWrapper (F f, Args&& ... args)
{
return std::thread ([f, args...] () { preamble (); f (std::forward <Args...> (args...)); });
};
int main()
{
std::thread t = ThreadWrapper ([] (std::string s) { std::cout << s << "n"; }, "42");
t.join ();
}
输出:
preamble
42
现场演示
今天早上醒来时我就想通了:) 由于 std::thread 衰减了它传递给函数的所有参数,因此当它调用我的包装方法时,参数是衰减的类型。 但是,当我传递模板参数进行包装时<>它会得到未衰减的类型:
std::thread( AppThread::wrap<Function,Args...>,
解决方案很简单,我需要在实例化模板包装方法之前衰减类型:
std::thread( AppThread::wrap<std::decay_t<Function>,std::decay_t<Args>...>,
相关文章:
- 从不同线程使用int64的不同字节安全吗
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 在C++中使用cURL和多线程
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在cuda线程之间共享大量常量数据
- 如何将元素添加到数组的线程安全函数?
- 线程构造函数周围的可变参数模板包装器无法编译
- 如何正确扩展 std::thread 来包装生成的线程
- 从包装器类scoped_thread中运行的线程中没有ouput
- 处理 std::线程包装器类的立即销毁
- 为多线程环境包装 c++ new/delete 的安全/好方法
- 包装标准::线程调用函数
- 重写 C++ STL 分配器函数以将其包装为线程安全
- 将参数传递给 std::线程包装器
- 多线程包装器
- 从 C++ => C 包装的 API(多线程)传输错误字符串
- 编写C API的线程安全C++包装器的努力
- 线程包装器实现问题
- std::unordered_map 上的线程安全包装器
- 是否使用类包装器对符合 C++11 的对象进行线程安全访问