Isn't placing the clean up code in the destructor more or less safer than using another method to do the trick?
The problem here is that while ExitThread (and other functions like it) is a perfect API for C, with C++ code, it breaks stack unwinding.
The correct solution for C++ is to make sure you do not call ExitThread (and such) in code using anything with destructors.
Problem:
void thread_function()
{
raii_resource r { acquire_resource() };
ExitThread();
// problem: r.~raii_resource() not called
}
The shutdown solution:
void thread_function()
{
raii_resource r { acquire_resource() };
r.shutdown(); // release resources here
ExitThread();
// r.~raii_resource() still not called
}
The shutdown solution is not obvious at all in client code. As @stefan said, kill it with fire.
Better solution (than the Shutdown thing):
void thread_function()
{
{ // artificial scope where RAII objects live
raii_resource r { acquire_resource() };
}
// this space does not support RAII life
ExitThread();
}
RAII works fine here, but the artificial scope is not very elegant. On top, it's as inelegant as the shutdown solution (it requires a non-obvious artifice in client code).
Better (cleaner) solution:
template<typename F>
void run_thread(F functor)
{
functor(); // all RAII resources inside functor; this is simple and
// obvious from client code
ExitThread();
}