Direct support for double-check worth the trouble?

I suspect blogs are like poetry - more are written than read. I've had this specific posting lost twice now by the system, so I'll need a total of three readers to break even.

I'm the lead developer for Intel® Threading Building Blocks (Intel® TBB). I've been pondering whether TBB should have more direct support for the double-check pattern. Scott Meyer's article explains why it is hard to get right. In TBB, the correct memory fences for it can be implied with the atomic<T> template, by writing it like this:

 // At file scope tbb::atomic<int> resource_is_ready; tbb::mutex initialization_mutex;

 // At function scope if( !resource_is_ready ) { tbb::mutex::scoped_lock lock(initialization_mutex); if( !resource_is_ready ) { ...initialize resource... resource_is_ready = true; } }

We could add more direct support, but I'm undecided on whether it is worth the trouble. If we add more direct support, the above fragment might look something like:

 // At file scope tbb::one_time my_is_ready; // At function scope TBB_ONE_TIME( my_is_ready ) { initialize resource my_is_ready.mark_done(); }

where TBB_ONE_TIME would be a macro that expands to something like "if( T _tbb_internal_var(ready) )", where T is a type internal to TBB. The reason for the temporary variable in the "if" would be to provide exception safety. If the destructor for _tbb_internal_var were called before the call to my_is_ready.mark_done(), then the implementation would know that an exception had been thrown and the resource was not successfully initialized.

While the more direct support would save some typing, it might add to the learning curve for TBB. So is the direct support worth the trouble? Is there a better way to provide the direct support? Or does the first pattern that I showed suffice?

- Arch

P.S. While writing the earlier draft that was lost, I discovered that we accidentally omitted atomic<bool> from TBB. That's something we plan to fix.