atomic_flag
is a really low level construct which isn't meant to be widely used. That said, I believe you're usage works as you intend, except possibly clearing the flag in exceptional cases. If an exception other than one matched by std::exception
occurs the flag does not get cleared.
Typically RAII should be used for this sort of thing. 'R' normally stands for 'resource' but I like Jon Kalb's usage of 'responsibility' instead. After setting the flag you have a responsibility to clear the flag when done, so you should use RAII to ensure that responsibility is carried out. If all of the things you need to do in exceptional cases can be done this way then the try
/catch
pair disappears.
if ( !std::atomic_flag_test_and_set( &::_my_flag ) )
{
flag_clearer x(&::_my_flag);
// do my stuff here
}
But you don't need to write a flag_clearer
type yourself. Instead you can simply use higher level constructs such as a mutex 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's exit
}