- std::thread does not follow RAII principles - 9 Updates
- Merry CHRISTmas! - 1 Update
- recovering from std::bad_alloc in std::string reserve - 6 Updates
- A single linked list using a futex... - 9 Updates
| Juha Nieminen <nospam@thanks.invalid>: May 26 11:51AM I have noticed a rather odd, and somewhat annoying, design decision in std::thread, which breaks RAII design. Normally when you use a C++ class from the standard library which allocates some resource, the class in question will make sure to properly freeing that resource when the object is destroyed, which is par for the course in good RAII design. For example, rather obviously, if you create an object of type std::vector, it will delete its allocated memory (and destroy the elements) when it's itself destroyed. A more noteworthy example of something that allocates a resource other than memory is std::ofstream: When it's destroyed, if it has a file open, it will properly close the file. This adds safety because it minimizes the risk of mistakes, especially since functions may be exited at surprising places thanks to exceptions. Like: void foo() { std::ofstream os("somefile"); doSomething(); // this might throw! // ... } No matter how that function is exited, even if an exception is thrown, that std::ofstream object will close the file so that the file handle isn't leaked. But now we come to std::thread. Suppose you have something like: void foo() { std::thread t(someFunction); doSomething(); signalTheThreadToStop(); t.join(); } The problem with this is that if doSomething() throws an exception, the program will crash. It doesn't even matter that you may be prepared for the exception, like: try { foo(); } catch(...) { std::cout << "Exception thrown!\n"; } the program will still crash, because std::thread does not like being destroyed without being joined or detached, so it just terminates if that's the case. This is quite inconvenient, and as far as I know the standard library doesn't really offer any utility to make disposing of the thread properly more automatic. You'll have to write your own "thread handler" that will terminate the thread properly when the thread object is destroyed, so that the program won't crash if the function is exited unexpectedly. This feels very counter to RAII principles, where objects should take care of the resources they have allocated, rather than demanding the calling code to manually do so. |
| Bonita Montero <Bonita.Montero@gmail.com>: May 26 02:04PM +0200 > the program will still crash, because std::thread does not like being > destroyed without being joined or detached, so it just terminates if that's > the case. Where's the problem ? Use a scrope-guard which waits for the end of the thread or a jthread with C++. That's my scope-guard class: #pragma once #include <cassert> #include "debug_exceptions.h" template<typename T> struct invoke_on_destruct { private: T m_t; bool m_enabled; public: invoke_on_destruct( T t ) : m_t( t ), m_enabled( true ) { } ~invoke_on_destruct() { if( m_enabled ) { try_debug { m_t(); } catch_debug { assert(false); } } } void disable_and_invoke() { m_enabled = false; m_t(); } void disable() { m_enabled = false; } void enable() { m_enabled = true; } }; #if defined(IOD_SHORT) template<typename C> using iod = invoke_on_destruct<C>; #define IOD(varName, lambdaName) \ iod<decltype(lambdaName)> varName( lambdaName );
Subscribe to:
Post Comments (Atom)
|
No comments:
Post a Comment