Boost C++ Libraries: Ticket #3407: boost::call_once not re-entrant (at least in win32) https://svn.boost.org/trac10/ticket/3407 <p> The win32 implementation of boost::call_once ( boost/thread/win32/once.hpp version 1.40.0 ) is not reentrant for the same thread. The problem happens on line 127. The function is called, and then the flag is set. This order should be reversed, the flag should be set and then the function should be called. If the function throws, the flag must be set back. </p> <p> This program demonstrates the issue: </p> <p> #include &lt;boost/thread/once.hpp&gt; </p> <p> static boost::once_flag flag; </p> <p> void called_twice() { </p> <blockquote> <p> boost::call_once( called_twice, flag ); </p> </blockquote> <blockquote> <p> <em> gets here twice </em></p> </blockquote> <p> } </p> <p> int main() { </p> <blockquote> <p> boost::call_once( called_twice, flag ); </p> </blockquote> <p> } </p> <p> While this may seem like a contrived example, it can easily happen in practice. Consider the case of a boost::singleton constructor that calls a function which then accesses its 'instance' member. The result will be that the singleton is created twice, because call_once is not re-entrant. </p> <p> Also consider the case of two singletons, A and B. A calls methods on B from its constructor, and B calls methods on A from its constructor. A will be created twice due to the non-reentrant behavior of call_once. </p> <p> I have not studied the behavior of call_once for other platforms. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/3407 Trac 1.4.3 Steven Watanabe Sun, 06 Sep 2009 14:58:26 GMT <link>https://svn.boost.org/trac10/ticket/3407#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3407#comment:1</guid> <description> <p> The flag must be set after the function is called. The reason is that if another thread calls call_once, it should block until the function is completed. I'll also point out that there is no good behavior for a recursive call to call_once. If it calls the function again, then f will be called twice. If it does not, then whatever initialization that call_once is doing may be incomplete. In either case, you have to know whether a call can be recursive and carefully design for it. If it happens accidentally, you're probably toast regardless of how it behaves. In the face of recursive calls it is impossible to maintain the post-condition that the function has run exactly once. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Fri, 20 Nov 2009 10:47:12 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3407#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3407#comment:2</guid> <description> <p> As this works as expected, Anthony could just add on the documentation why re-entrant call_once functions are not a good idea? The explanation of Steven could be a good starting point. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Fri, 20 Nov 2009 10:47:53 GMT</pubDate> <title>component changed https://svn.boost.org/trac10/ticket/3407#comment:3 https://svn.boost.org/trac10/ticket/3407#comment:3 <ul> <li><strong>component</strong> <span class="trac-field-old">threads</span> → <span class="trac-field-new">thread</span> </li> </ul> Ticket Anthony Williams Mon, 23 Nov 2009 11:32:13 GMT status changed; resolution set https://svn.boost.org/trac10/ticket/3407#comment:4 https://svn.boost.org/trac10/ticket/3407#comment:4 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">wontfix</span> </li> </ul> <p> Documentation updated, changeset 57862 </p> Ticket