As the code below shows, I am trying to implement my own thread class by passing in a packaged_task. I then wait on the future from this packaged_task. I expect this code to wait 4 seconds and then I can get 0xcdcdcdcd from the future.
#include <iostream>
#include <future>
using namespace std;
class mythread {
public:
thread internal_thread;
template <typename _Fn> mythread(_Fn f) {
internal_thread = thread([&f] {
try {
f();
}
catch (std::exception& e) {
this_thread::sleep_for(chrono::seconds(4));
std::cout << e.what() << std::endl;
}
});
}
};
int work() {
this_thread::sleep_for(chrono::milliseconds(2000));
return 0xcdcdcdcd;
}
int main() {
packaged_task<int()> task(work);
future<int> ftr = task.get_future();
mythread thrd(move(task));
ftr.wait();
cout << "Got it!!" << endl;
try {
cout << ftr.get() << endl;
}
catch (future_error &e) {
std::cout << "outer " << e.code() << e.what() << std::endl;
}
cout << "Ended" << endl;
getchar();
}
But the wait seems to terminate this task immediately. By compiling executing this code, it immediately prints out
Got it!!
outer future:4unspecified future_errc value
Ended
The environment is OS X 10.11.1,
$ g++ -v
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin15.0.0
Thread model: posix
The compiling command is
g++ --std=c++11 main.cpp && ./a.out
I'm not sure if it reproduces on other platforms.
Thanks in advance.
Edit
Solved: It is because the constructor of mythread
now takes control of the life time of f
moved in, whose reference is used by the thread. But the constructor returns immediately after creating the thread, thus destroying every local variables, including f
, while the thread is still holding that destroyed local variable.
The corrected code is
class mythread {
public:
thread internal_thread;
template <typename _Fn> mythread(_Fn f) {
internal_thread = thread([] (_Fn f) {
try {
f();
}
catch (std::exception& e) {
this_thread::sleep_for(chrono::seconds(4));
std::cout << e.what() << std::endl;
}
}, move(f));
}
};
Where the control of f
is further moved into the thread.