I want to set up an invocation of a function (or lambda function) to happen automatically when the current thread exits, but I cannot see any way to do it that works with std::thread
unless I take over the entire task of thread creation or manually ensure that every thread calls some particular function that I always provide as its very last operation.
Essentially, I want function whose prototype may resemble something like this:
on_thread_exit(const std::function<void()> &func);
Which would perform whatever setup was necessary to ensure that the given function was automatically called when the thread which called on_thread_exit eventually terminates, and without requiring any particular functions to be explicitly called at thread creation or termination.
The C++11 does not have direct method to terminate the threads. The std::future<void> can be used to the thread, and it should exit when value in future is available. If we want to send a signal to the thread, but does not send the actual value, we can pass void type object.
The pthread_exit() function terminates the calling thread, making its exit status available to any waiting threads. Normally, a thread terminates by returning from the start routine that was specified in the pthread_create() call which started it.
Calling the exit subroutine terminates the entire process, including all its threads. In a multithreaded program, the exit subroutine should only be used when the entire process needs to be terminated; for example, in the case of an unrecoverable error.
You can do it using thread_local
storage, since C++11 should call the destructors after the thread exits. You'll have to make sure you have a compiler that supports that properly.
#include <stack>
#include <function>
void on_thread_exit(std::function<void()> func)
{
class ThreadExiter
{
std::stack<std::function<void()>> exit_funcs;
public:
ThreadExiter() = default;
ThreadExiter(ThreadExiter const&) = delete;
void operator=(ThreadExiter const&) = delete;
~ThreadExiter()
{
while(!exit_funcs.empty())
{
exit_funcs.top()();
exit_funcs.pop();
}
}
void add(std::function<void()> func)
{
exit_funcs.push(std::move(func));
}
};
thread_local ThreadExiter exiter;
exiter.add(std::move(func));
}
Basically, this function creates a thread_local
object of the above class. This is basically static, except is destroyed when the thread exits. When called, it pushes the function onto the vector, and when its destroyed it runs the functions.
You can use it by calling on_thread_exit()
from any thread, which will create the exit object, which will run your function in the reverse order that it was put into the thread queue (feel free to modify as you see fit).
Here is a simplified/shortened version based on Dave S's solution that uses more C++11 features with the following properties:
ThreadExiter
is only used once, we can combine the variable declaration, avoid public
/private
(class
to struct
) and remove the copy constructor/assignment operatorstd::stack
with range-based for loop and std::deque
add()
methodNote that this destructs the callback functions from the std::deque
only after all have been called, which might or might not be what you want -- if you require the function object to be destroyed after it has been called (and before any other function objects are called), use a stack and pop elements like in Dave's solution).
Code:
#include <functional>
#include <deque>
void
on_thread_exit(std::function<void()> func)
{
thread_local struct ThreadExiter {
std::deque<std::function<void()>> callbacks;
~ThreadExiter() {
for (auto &callback: callbacks) {
callback();
}
}
} exiter;
exiter.callbacks.emplace_front(std::move(func));
}
You may use BOOST_SCOPE_EXIT
For the the main thread:
void on_thread_exit();
void main( int argc, char** argv )
{
BOOST_SCOPE_EXIT() // may be one arg, at least, is required
{
on_thread_exit();
}BOOST_SCOPE_EXIT_END
...
}
I leave you to extrapolate any thread !
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With