One thing call_once
does for you is handle exceptions. That is, if the first thread into it throws an exception inside the functor (and propagates it), call_once
will not satisfy call_once
. A subsequent call is allowed to enter the functor again, trying to complete it without exception.
In your example, the exception case is also handled properly. However, it is easy to imagine a more complex functor where the exceptional case will not be properly handled.
All this suggests that call_once
redundant with the call_once
-statics function. For instance:.
CSingleton& CSingleton::GetInstance() { static std::unique_ptr<CSingleton> m_instance(new CSingleton); return *m_instance; }
Or easier:
CSingleton& CSingleton::GetInstance() { static CSingleton m_instance; return m_instance; }
The above is equivalent to your call_once
example, and imho is simpler. Oh, apart from the order of destruction, it is very subtly different from this and your example. In both cases, m_instance
destroyed in the reverse order of construction. But the construction order is different. In your m_instance
built in relation to other objects with a local-local area in the same translation unit. Using the m_instance
-statics function, m_instance
is created when m_instance
is executed.
This difference may or may not be important for your application. I usually prefer the function-locally-static solution, as it is "lazy". That is, if the application never calls GetInstance()
, then m_instance
never created. And there is no time during the launch of the application, when many statics are trying to build right away. You pay for the construction only in actual use.
source share