C ++ 11 std :: atomic_flag, am I using this correctly?

I have a simple boolean that I need to check and set in thread safe mode. If one thread is already running, I want the second thread to exit. If I understand std::atomic_flag , this should work fine. However, I'm not sure I understand std::atomic_flag :) I cannot find many simple examples on the Internet, except for this spin-lock example:

 // myclass.cpp #using <atomic> namespace // anonymous namespace { std::atomic_flag _my_flag = ATOMIC_FLAG_INIT; } // ns myclass::do_something() { if ( !::_my_flag.test_and_set() ) ) { // do my stuff here; handle errors and clear flag when done try { // do my stuff here } catch ( ... ) { // handle exception } ::_my_flag.clear(); // clear my flag, we're done doing stuff } // else, we're already doing something in another thread, let exit } // do_something 

Update: updated code based on the suggestions below, generating a suitable template for the correct use of std::atomic_flag . Thanks everyone!

+6
source share
2 answers

atomic_flag is a really low level construct that should not be widely used. However, I believe that you are using the work as you plan, with the possible exception of the possibility of removing the flag in exceptional cases. If an exception other than that corresponding to std::exception occurs, the flag is not cleared.

Normally RAII should be used for this kind of thing. "R" usually means "resource", but I like Jon Kalb's use of "responsibility." After setting the flag, you must clear the flag when it is done, so you should use RAII to ensure that the responsibility is fulfilled. If all you need to do in exceptional cases can be done this way, then the try / catch pair will disappear.

 if ( !std::atomic_flag_test_and_set( &::_my_flag ) ) { flag_clearer x(&::_my_flag); // do my stuff here } 

But you do not need to write the flag_clearer type yourself. Instead, you can simply use higher-level constructs such as mutexes and lock_guard:

 namespace { std::mutex my_flag; } myclass::do_something() { if ( my_flag.try_lock() ) { std::lock_guard<std::mutex> x(my_flag, std::adopt_lock); // do my stuff here } // else, we're already doing something in another thread, let exit } 
+5
source

Yes, this will skip the code inside the if block if any other thread has already set the flag and no one has cleared it. If no other code is placed with a flag, this means that some thread is currently executing this block.

Atomic flags are pretty low; use atomic_bool . Also, since this is C ++, you can use member functions to set and clear.

EDIT:

No, atomic_bool does not just do what you want. Stick to atomic_flag ...

+1
source

All Articles