OEOnce

template<class T>
struct OEOnce

OEOnce is deprecated. OpenEye strongly recommends using one of the alternatives below instead of `OEOnce`

OEOnce was created to facilitate thread-safe initialization of function-local-statics before C++11’s magic-statics were universally available. Its implementation has become redundant since moving to VS2015 with full C++11 compliance. All of the existing uses will continue to work as intended without change, with minimal overhead in compile and run time for optimized release builds, in most cases.

Alternatives

  • Function local static instances:

    • Only use when required - there is a performance cost!

    • Make const unless you can’t.

    • Fully construct static local in a single line:

      • Via constructor: static const SomeClass someInstance{"abc", 1.23f, 456};

      • Via function result: static const int tag = OEGetTag(”my_tag”);

      • Use std::unique_ptr when you must have a pointer, or for very large objects: static const std::unique_ptr<Class2> up{factoryFunc()};

  • When call-once is truly desired:

    • std::atomic_flag

      • Define at file scope if you can

      • init with = ATOMIC_FLAG_INIT;

      • Use std::atomic_flag::test_and_set in conditional

    • std::once_flag/call_once

      • Define std::once_flag at file scope if you can

      • Provides exception handling

      • Can handle more complex situations

Original Documentation

This class is used to do thread-safe one time initialization of an object as a function local static. It is intended to imitate the behavior of the C++11 “magic statics” feature. The default constructor of the class T is guaranteed to be called once, and only once, and all other threads will block until initialization is complete.

The following code snippet demonstrates how to use OEOnce to cache an initialized OESubSearch object to be used by subsequent function invocations:

class PhenylSubSearch
{
  OESubSearch _subsrch;
public:
  PhenylSubSearch() : _subsrch("c1ccccc1") { }
  const OESubSearch &GetSubSearch() const { return _subsrch; }
};

bool HasPhenyl(const OEMolBase &mol)
{
  static OEOnce<PhenylSubSearch> phenylSubSrch = OE_ONCE_INIT;
  return phenylSubSrch->GetSubSearch().SingleMatch(mol);
}

Warning

The thread safety of the object T is the responsibility of the user. OEOnce will only ensure that there is only one of them initialized for the whole lifetime of the process and that its destructor is called during process exit.

operator*

T &operator*()

Dereference that OEOnce object, returning a reference to the singleton T object. The reference will only be returned once at least one thread has fully initialized the object.

operator->

T *operator->()

Allows the OEOnce object to behave like a pointer to T. The pointer will only be returned once at least one thread has fully initialized the object.

operator T *

operator T *()

Allows the OEOnce object to be cast to a pointer of T. The pointer will only be returned once at least one thread has fully initialized the object.

GetValue

T *GetValue()

Returns the pointer to a singleton object initialized in a thread safe way. The pointer will only be returned once at least one thread has fully initialized the object.