指向成员对象的指针 - 中断线程
Pointer to member object - Interrupt Thread
这是我昨天回答的一个问题的后续。
我正在尝试为成员函数创建一个中断线程,但我不知道这些错误是什么:
[vagrant@localhost projects]$ g++ -o test test.cpp -lpthread
test.cpp: In instantiation of ‘InterruptibleThread::InterruptibleThread(Function&&, Args&& ...)::<lambda(std::atomic_bool&, std::atomic_bool&, auto:1&&, Args&& ...)> [with auto:1 = void (MyClass::*)(int); Function = void (MyClass::*)(int); Args = {MyClass*, int}; std::atomic_bool = std::atomic<bool>]’:
/usr/local/include/c++/6.3.0/type_traits:2481:26: required by substitution of ‘template<class _Fn, class ... _Args> static std::__result_of_success<decltype (declval<_Fn>()((declval<_Args>)()...)), std::__invoke_other> std::__result_of_other_impl::_S_test(int) [with _Fn = InterruptibleThread::InterruptibleThread(Function&&, Args&& ...) [with Function = void (MyClass::*)(int); Args = {MyClass*, int}]::<lambda(std::atomic_bool&, std::atomic_bool&, auto:1&&, MyClass*&&, int&&)>; _Args = {std::reference_wrapper<std::atomic<bool> >, std::reference_wrapper<std::atomic<bool> >, void (MyClass::*)(int), MyClass*, int}]’
/usr/local/include/c++/6.3.0/type_traits:2492:55: required from ‘struct std::__result_of_impl<false, false, InterruptibleThread::InterruptibleThread(Function&&, Args&& ...) [with Function = void (MyClass::*)(int); Args = {MyClass*, int}]::<lambda(std::atomic_bool&, std::atomic_bool&, auto:1&&, MyClass*&&, int&&)>, std::reference_wrapper<std::atomic<bool> >, std::reference_wrapper<std::atomic<bool> >, void (MyClass::*)(int), MyClass*, int>’
/usr/local/include/c++/6.3.0/type_traits:2496:12: required from ‘class std::result_of<InterruptibleThread::InterruptibleThread(Function&&, Args&& ...) [with Function = void (MyClass::*)(int); Args = {MyClass*, int}]::<lambda(std::atomic_bool&, std::atomic_bool&, auto:1&&, MyClass*&&, int&&)>(std::reference_wrapper<std::atomic<bool> >, std::reference_wrapper<std::atomic<bool> >, void (MyClass::*)(int), MyClass*, int)>’
/usr/local/include/c++/6.3.0/functional:1365:61: required from ‘struct std::_Bind_simple<InterruptibleThread::InterruptibleThread(Function&&, Args&& ...) [with Function = void (MyClass::*)(int); Args = {MyClass*, int}]::<lambda(std::atomic_bool&, std::atomic_bool&, auto:1&&, MyClass*&&, int&&)>(std::reference_wrapper<std::atomic<bool> >, std::reference_wrapper<std::atomic<bool> >, void (MyClass::*)(int), MyClass*, int)>’
/usr/local/include/c++/6.3.0/thread:137:26: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = InterruptibleThread::InterruptibleThread(Function&&, Args&& ...) [with Function = void (MyClass::*)(int); Args = {MyClass*, int}]::<lambda(std::atomic_bool&, std::atomic_bool&, auto:1&&, MyClass*&&, int&&)>; _Args = {std::reference_wrapper<std::atomic<bool> >, std::reference_wrapper<std::atomic<bool> >, void (MyClass::*)(int), MyClass*, int}]’
test.cpp:41:33: required from ‘InterruptibleThread::InterruptibleThread(Function&&, Args&& ...) [with Function = void (MyClass::*)(int); Args = {MyClass*, int}]’
test.cpp:111:53: required from here
test.cpp:36:9: error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘fxn (...)’, e.g. ‘(... ->* fxn) (...)’
fxn( forward< Args >( args )... );
当前代码:
using namespace std;
class InterruptThreadException {};
class InterruptibleThread {
private:
static thread_local atomic_bool* stopRef;
static thread_local atomic_bool* pauseRef;
atomic_bool stopFlag{false};
atomic_bool pauseFlag{false};
thread thrd;
public:
friend void checkForInterrupt( );
template < typename Function, typename... Args >
InterruptibleThread( Function&& _fxn, Args&&... _args )
: thrd(
[]( atomic_bool& sr, atomic_bool& pr, auto&& fxn, Args&&... args ) {
stopRef = &sr;
pauseRef = ≺
fxn( forward< Args >( args )... );
},
ref( stopFlag ),
ref( pauseFlag ),
forward< Function >( _fxn ),
forward< Args >( _args )... ) {
thrd.detach( );
}
bool stopping( ) const {
return stopFlag.load( );
}
void stop( ) {
stopFlag.store( true );
}
void pause( ) {
pauseFlag.store( true );
cout << "setting pause flag: " << pauseFlag.load( ) << endl;
}
void start( ) {
pauseFlag.store( false );
}
};
void checkForInterrupt( ) {
cout << "Pause flag: " << InterruptibleThread::pauseRef->load( ) << endl;
cout << "Stop flag: " << InterruptibleThread::stopRef->load( ) << endl;
while ( InterruptibleThread::pauseRef->load( ) ) {
cout << "Pausedn";
this_thread::sleep_for( chrono::seconds( 1 ) );
}
if ( !InterruptibleThread::stopRef->load( ) ) {
return;
}
throw InterruptThreadException( );
}
thread_local atomic_bool* InterruptibleThread::stopRef = nullptr;
thread_local atomic_bool* InterruptibleThread::pauseRef = nullptr;
void doWork( ) {
int i = 0;
try {
while ( true ) {
cout << "Checking for interrupt: " << i++ << endl;
checkForInterrupt( );
this_thread::sleep_for( chrono::seconds( 1 ) );
}
} catch ( InterruptThreadException ) {
cout << "Interruptednn";
}
}
class MyClass {
private:
int myInt;
void setInt( int i ) {
myInt = i;
}
public:
MyClass( ) : myInt( 1 ) {
}
void myWork( int i );
void doWork( );
};
void MyClass::myWork( int i ) {
setInt( i );
cout << "myInt value: " << myInt << endl;
}
void MyClass::doWork( ) {
InterruptibleThread t( &MyClass::myWork, this, 666 );
}
int main( ) {
MyClass mc;
mc.doWork( );
cout << "Press enter to exit" << endl;
getchar( );
return 0;
}
我尝试了编译器建议,之后遇到了与折叠表达式相关的错误(afaik 是 C++17,我不要使用超过 14 的任何内容(。知道如何让它工作吗?
我有一个不使用lambdas的工作版本,但我真的很好奇如何让它与原始代码一起使用。
调用指向成员函数的指针的语法与指向非成员函数或其他函子的指针不同。 由于Function
在您的情况下是一个void (MyClass::*)(int)
,您需要使用语法(object.*fxn)(arg)
或(objectPtr->*fxn)(arg)
来调用它。
如果您有权访问 C++17 功能,则可以使用std::invoke
统一调用不同类型的可调用对象:
InterruptibleThread( Function&& _fxn, Args&&... _args )
: thrd(
[]( atomic_bool& sr, atomic_bool& pr, auto&& fxn, auto&&... args ) {
stopRef = &sr;
pauseRef = ≺
std::invoke(std::move(fxn), std::move(args)...);
},
//...
注意:我Args&&... args
更改为auto&&... args
Args&&...
因为这可能会导致问题。
如果您无法访问 C++17,您可以相当轻松地自己实现invoke
:
template <typename Callable,
typename... Args,
typename = std::enable_if_t<!std::is_member_function_pointer<Callable>::value>>
decltype(auto) invoke(Callable&& c, Args&&... args) {
return std::forward<Callable>(c)(std::forward<Args>(args)...);
}
template <typename T,
typename T2,
typename Ret,
typename... FuncArgs,
typename... Args,
typename = std::enable_if_t<!std::is_pointer<T2>::value>>
decltype(auto) invoke(Ret (T::*c)(FuncArgs...), T2&& t, Args&&... args) {
return (std::forward<T>(t).*c)(std::forward<Args>(args)...);
}
template <typename T,
typename T2,
typename Ret,
typename... FuncArgs,
typename... Args>
decltype(auto) invoke(Ret (T::*c)(FuncArgs...), T2* t, Args&&... args) {
return (t->*c)(std::forward<Args>(args)...);
}
这不会做std::invoke
所做的一切,但它会做你需要它的一切。
相关文章:
- 使用 shared_ptr 在中断时结束多线程循环
- 如何使用 SIGINT 在第二个线程中断 getchar
- 可中断线程类 C++11 - 遇到错误?
- 指向成员对象的指针 - 中断线程
- 处理中断时,如何回到主gui线程
- 在 Visual Studio 中的调试中断时设置默认线程,C++
- 返回可中断线程的函数
- 多线程应用程序中的零MQ处理中断
- C++等待用户输入的中断线程
- 如何中断Asynch线程
- 捕获升压线程中断和退出线程的正确方法
- 中断已处于条件变量等待调用中的提升线程
- 中断正在执行MKL或其他第三方函数的线程
- 为什么我不能中断这个特定的提升::线程?
- 《C++并发在行动》中的可中断线程示例
- 使用 Boost::thread 实现可中断线程
- 可以优化中断线程安全
- Windows API中的不可中断线程部分
- 在一定时间后中断线程,在等待时不阻塞
- 为什么此代码被认为是可重复的,以及当操作系统中断线程时究竟会发生什么