• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef BOOST_THREAD_PTHREAD_ONCE_HPP
2 #define BOOST_THREAD_PTHREAD_ONCE_HPP
3 
4 //  once.hpp
5 //
6 //  (C) Copyright 2007-8 Anthony Williams
7 //  (C) Copyright 2011-2012 Vicente J. Botet Escriba
8 //
9 //  Distributed under the Boost Software License, Version 1.0. (See
10 //  accompanying file LICENSE_1_0.txt or copy at
11 //  http://www.boost.org/LICENSE_1_0.txt)
12 
13 #include <boost/thread/detail/config.hpp>
14 #include <boost/thread/detail/move.hpp>
15 #include <boost/thread/detail/invoke.hpp>
16 
17 #include <boost/thread/pthread/pthread_helpers.hpp>
18 #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
19 #include <boost/thread/detail/delete.hpp>
20 #include <boost/core/no_exceptions_support.hpp>
21 
22 #include <boost/bind/bind.hpp>
23 #include <boost/assert.hpp>
24 #include <boost/config/abi_prefix.hpp>
25 
26 #include <boost/cstdint.hpp>
27 #include <pthread.h>
28 #include <csignal>
29 
30 namespace boost
31 {
32 
33   struct once_flag;
34 
35   #define BOOST_ONCE_INITIAL_FLAG_VALUE 0
36 
37   namespace thread_detail
38   {
39     typedef boost::uint32_t  uintmax_atomic_t;
40     #define BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_C2(value) value##u
41     #define BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_C2(~0)
42 
43   }
44 
45 #ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
46 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
47     template<typename Function, class ...ArgTypes>
48     inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args);
49 #else
50     template<typename Function>
51     inline void call_once(once_flag& flag, Function f);
52     template<typename Function, typename T1>
53     inline void call_once(once_flag& flag, Function f, T1 p1);
54     template<typename Function, typename T1, typename T2>
55     inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2);
56     template<typename Function, typename T1, typename T2, typename T3>
57     inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3);
58 #endif
59 
60   struct once_flag
61   {
BOOST_THREAD_NO_COPYABLEboost::once_flag62       BOOST_THREAD_NO_COPYABLE(once_flag)
63       BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT
64         : epoch(BOOST_ONCE_INITIAL_FLAG_VALUE)
65       {}
66   private:
67       volatile thread_detail::uintmax_atomic_t epoch;
68 
69 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
70       template<typename Function, class ...ArgTypes>
71       friend void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args);
72 #else
73       template<typename Function>
74       friend void call_once(once_flag& flag, Function f);
75       template<typename Function, typename T1>
76       friend void call_once(once_flag& flag, Function f, T1 p1);
77       template<typename Function, typename T1, typename T2>
78       friend void call_once(once_flag& flag, Function f, T1 p1, T2 p2);
79       template<typename Function, typename T1, typename T2, typename T3>
80       friend void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3);
81 
82 #endif
83 
84   };
85 
86 #define BOOST_ONCE_INIT once_flag()
87 
88 #else // BOOST_THREAD_PROVIDES_ONCE_CXX11
89 
90     struct once_flag
91     {
92       volatile thread_detail::uintmax_atomic_t epoch;
93     };
94 
95 #define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE}
96 #endif // BOOST_THREAD_PROVIDES_ONCE_CXX11
97 
98 
99 #if defined BOOST_THREAD_PROVIDES_INVOKE
100 #define BOOST_THREAD_INVOKE_RET_VOID detail::invoke
101 #define BOOST_THREAD_INVOKE_RET_VOID_CALL
102 #elif defined BOOST_THREAD_PROVIDES_INVOKE_RET
103 #define BOOST_THREAD_INVOKE_RET_VOID detail::invoke<void>
104 #define BOOST_THREAD_INVOKE_RET_VOID_CALL
105 #else
106 #define BOOST_THREAD_INVOKE_RET_VOID boost::bind
107 #define BOOST_THREAD_INVOKE_RET_VOID_CALL ()
108 #endif
109 
110     namespace thread_detail
111     {
112         BOOST_THREAD_DECL uintmax_atomic_t& get_once_per_thread_epoch();
113         BOOST_THREAD_DECL extern uintmax_atomic_t once_global_epoch;
114         BOOST_THREAD_DECL extern pthread_mutex_t once_epoch_mutex;
115         BOOST_THREAD_DECL extern pthread_cond_t once_epoch_cv;
116     }
117 
118     // Based on Mike Burrows fast_pthread_once algorithm as described in
119     // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2444.html
120 
121 
122 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
123 
124 
125   template<typename Function, class ...ArgTypes>
call_once(once_flag & flag,BOOST_THREAD_RV_REF (Function)f,BOOST_THREAD_RV_REF (ArgTypes)...args)126   inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args)
127   {
128     static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
129     static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1;
130     thread_detail::uintmax_atomic_t const epoch=flag.epoch;
131     thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch();
132 
133     if(epoch<this_thread_epoch)
134     {
135         pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex);
136 
137         while(flag.epoch<=being_initialized)
138         {
139             if(flag.epoch==uninitialized_flag)
140             {
141                 flag.epoch=being_initialized;
142                 BOOST_TRY
143                 {
144                     pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex);
145                     BOOST_THREAD_INVOKE_RET_VOID(
146                         thread_detail::decay_copy(boost::forward<Function>(f)),
147                         thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
148                     ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
149                 }
150                 BOOST_CATCH (...)
151                 {
152                     flag.epoch=uninitialized_flag;
153                     BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
154                     BOOST_RETHROW
155                 }
156                 BOOST_CATCH_END
157                 flag.epoch=--thread_detail::once_global_epoch;
158                 BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
159             }
160             else
161             {
162                 while(flag.epoch==being_initialized)
163                 {
164                     BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
165                 }
166             }
167         }
168         this_thread_epoch=thread_detail::once_global_epoch;
169 
170     }
171   }
172 #else
173   template<typename Function>
call_once(once_flag & flag,Function f)174   inline void call_once(once_flag& flag, Function f)
175   {
176     static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
177     static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1;
178     thread_detail::uintmax_atomic_t const epoch=flag.epoch;
179     thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch();
180 
181     if(epoch<this_thread_epoch)
182     {
183         pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex);
184 
185         while(flag.epoch<=being_initialized)
186         {
187             if(flag.epoch==uninitialized_flag)
188             {
189                 flag.epoch=being_initialized;
190                 BOOST_TRY
191                 {
192                     pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex);
193                     f();
194                 }
195                 BOOST_CATCH (...)
196                 {
197                     flag.epoch=uninitialized_flag;
198                     BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
199                     BOOST_RETHROW
200                 }
201                 BOOST_CATCH_END
202                 flag.epoch=--thread_detail::once_global_epoch;
203                 BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
204             }
205             else
206             {
207                 while(flag.epoch==being_initialized)
208                 {
209                     BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
210                 }
211             }
212         }
213         this_thread_epoch=thread_detail::once_global_epoch;
214     }
215   }
216 
217   template<typename Function, typename T1>
call_once(once_flag & flag,Function f,T1 p1)218   inline void call_once(once_flag& flag, Function f, T1 p1)
219   {
220     static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
221     static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1;
222     thread_detail::uintmax_atomic_t const epoch=flag.epoch;
223     thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch();
224 
225     if(epoch<this_thread_epoch)
226     {
227         pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex);
228 
229         while(flag.epoch<=being_initialized)
230         {
231             if(flag.epoch==uninitialized_flag)
232             {
233                 flag.epoch=being_initialized;
234                 BOOST_TRY
235                 {
236                     pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex);
237                     BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL;
238                 }
239                 BOOST_CATCH (...)
240                 {
241                     flag.epoch=uninitialized_flag;
242                     BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
243                     BOOST_RETHROW
244                 }
245                 BOOST_CATCH_END
246                 flag.epoch=--thread_detail::once_global_epoch;
247                 BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
248             }
249             else
250             {
251                 while(flag.epoch==being_initialized)
252                 {
253                     BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
254                 }
255             }
256         }
257         this_thread_epoch=thread_detail::once_global_epoch;
258     }
259   }
260   template<typename Function, typename T1, typename T2>
call_once(once_flag & flag,Function f,T1 p1,T2 p2)261   inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2)
262   {
263     static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
264     static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1;
265     thread_detail::uintmax_atomic_t const epoch=flag.epoch;
266     thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch();
267 
268     if(epoch<this_thread_epoch)
269     {
270         pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex);
271 
272         while(flag.epoch<=being_initialized)
273         {
274             if(flag.epoch==uninitialized_flag)
275             {
276                 flag.epoch=being_initialized;
277                 BOOST_TRY
278                 {
279                     pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex);
280                     BOOST_THREAD_INVOKE_RET_VOID(f,p1, p2) BOOST_THREAD_INVOKE_RET_VOID_CALL;
281         }
282                 BOOST_CATCH (...)
283                 {
284                     flag.epoch=uninitialized_flag;
285                     BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
286                     BOOST_RETHROW
287                 }
288                 BOOST_CATCH_END
289                 flag.epoch=--thread_detail::once_global_epoch;
290                 BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
291             }
292             else
293             {
294                 while(flag.epoch==being_initialized)
295                 {
296                     BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
297                 }
298             }
299         }
300         this_thread_epoch=thread_detail::once_global_epoch;
301     }
302   }
303 
304   template<typename Function, typename T1, typename T2, typename T3>
call_once(once_flag & flag,Function f,T1 p1,T2 p2,T3 p3)305   inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3)
306   {
307     static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
308     static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1;
309     thread_detail::uintmax_atomic_t const epoch=flag.epoch;
310     thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch();
311 
312     if(epoch<this_thread_epoch)
313     {
314         pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex);
315 
316         while(flag.epoch<=being_initialized)
317         {
318             if(flag.epoch==uninitialized_flag)
319             {
320                 flag.epoch=being_initialized;
321                 BOOST_TRY
322                 {
323                     pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex);
324                     BOOST_THREAD_INVOKE_RET_VOID(f,p1, p2, p3) BOOST_THREAD_INVOKE_RET_VOID_CALL;
325         }
326                 BOOST_CATCH (...)
327                 {
328                     flag.epoch=uninitialized_flag;
329                     BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
330                     BOOST_RETHROW
331                 }
332                 BOOST_CATCH_END
333                 flag.epoch=--thread_detail::once_global_epoch;
334                 BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
335             }
336             else
337             {
338                 while(flag.epoch==being_initialized)
339                 {
340                     BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
341                 }
342             }
343         }
344         this_thread_epoch=thread_detail::once_global_epoch;
345     }
346   }
347 
348   template<typename Function>
call_once(once_flag & flag,BOOST_THREAD_RV_REF (Function)f)349   inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f)
350   {
351     static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
352     static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1;
353     thread_detail::uintmax_atomic_t const epoch=flag.epoch;
354     thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch();
355 
356     if(epoch<this_thread_epoch)
357     {
358         pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex);
359 
360         while(flag.epoch<=being_initialized)
361         {
362             if(flag.epoch==uninitialized_flag)
363             {
364                 flag.epoch=being_initialized;
365                 BOOST_TRY
366                 {
367                     pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex);
368                     f();
369                 }
370                 BOOST_CATCH (...)
371                 {
372                     flag.epoch=uninitialized_flag;
373                     BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
374                     BOOST_RETHROW
375                 }
376                 BOOST_CATCH_END
377                 flag.epoch=--thread_detail::once_global_epoch;
378                 BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
379             }
380             else
381             {
382                 while(flag.epoch==being_initialized)
383                 {
384                     BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
385                 }
386             }
387         }
388         this_thread_epoch=thread_detail::once_global_epoch;
389     }
390   }
391 
392   template<typename Function, typename T1>
call_once(once_flag & flag,BOOST_THREAD_RV_REF (Function)f,BOOST_THREAD_RV_REF (T1)p1)393   inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1)
394   {
395     static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
396     static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1;
397     thread_detail::uintmax_atomic_t const epoch=flag.epoch;
398     thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch();
399 
400     if(epoch<this_thread_epoch)
401     {
402         pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex);
403 
404         while(flag.epoch<=being_initialized)
405         {
406             if(flag.epoch==uninitialized_flag)
407             {
408                 flag.epoch=being_initialized;
409                 BOOST_TRY
410                 {
411                     pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex);
412                     BOOST_THREAD_INVOKE_RET_VOID(
413                         thread_detail::decay_copy(boost::forward<Function>(f)),
414                         thread_detail::decay_copy(boost::forward<T1>(p1))
415                     ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
416                 }
417                 BOOST_CATCH (...)
418                 {
419                     flag.epoch=uninitialized_flag;
420                     BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
421                     BOOST_RETHROW
422                 }
423                 BOOST_CATCH_END
424                 flag.epoch=--thread_detail::once_global_epoch;
425                 BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
426             }
427             else
428             {
429                 while(flag.epoch==being_initialized)
430                 {
431                     BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
432                 }
433             }
434         }
435         this_thread_epoch=thread_detail::once_global_epoch;
436     }
437   }
438   template<typename Function, typename T1, typename T2>
call_once(once_flag & flag,BOOST_THREAD_RV_REF (Function)f,BOOST_THREAD_RV_REF (T1)p1,BOOST_THREAD_RV_REF (T2)p2)439   inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2)
440   {
441     static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
442     static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1;
443     thread_detail::uintmax_atomic_t const epoch=flag.epoch;
444     thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch();
445 
446     if(epoch<this_thread_epoch)
447     {
448         pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex);
449 
450         while(flag.epoch<=being_initialized)
451         {
452             if(flag.epoch==uninitialized_flag)
453             {
454                 flag.epoch=being_initialized;
455                 BOOST_TRY
456                 {
457                     pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex);
458                     BOOST_THREAD_INVOKE_RET_VOID(
459                         thread_detail::decay_copy(boost::forward<Function>(f)),
460                         thread_detail::decay_copy(boost::forward<T1>(p1)),
461                         thread_detail::decay_copy(boost::forward<T1>(p2))
462                     ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
463                 }
464                 BOOST_CATCH (...)
465                 {
466                     flag.epoch=uninitialized_flag;
467                     BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
468                     BOOST_RETHROW
469                 }
470                 BOOST_CATCH_END
471                 flag.epoch=--thread_detail::once_global_epoch;
472                 BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
473             }
474             else
475             {
476                 while(flag.epoch==being_initialized)
477                 {
478                     BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
479                 }
480             }
481         }
482         this_thread_epoch=thread_detail::once_global_epoch;
483     }
484   }
485 
486   template<typename Function, typename T1, typename T2, typename T3>
call_once(once_flag & flag,BOOST_THREAD_RV_REF (Function)f,BOOST_THREAD_RV_REF (T1)p1,BOOST_THREAD_RV_REF (T2)p2,BOOST_THREAD_RV_REF (T3)p3)487   inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2, BOOST_THREAD_RV_REF(T3) p3)
488   {
489     static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
490     static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1;
491     thread_detail::uintmax_atomic_t const epoch=flag.epoch;
492     thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch();
493 
494     if(epoch<this_thread_epoch)
495     {
496         pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex);
497 
498         while(flag.epoch<=being_initialized)
499         {
500             if(flag.epoch==uninitialized_flag)
501             {
502                 flag.epoch=being_initialized;
503                 BOOST_TRY
504                 {
505                     pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex);
506                     BOOST_THREAD_INVOKE_RET_VOID(
507                         thread_detail::decay_copy(boost::forward<Function>(f)),
508                         thread_detail::decay_copy(boost::forward<T1>(p1)),
509                         thread_detail::decay_copy(boost::forward<T1>(p2)),
510                         thread_detail::decay_copy(boost::forward<T1>(p3))
511                     ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
512                 }
513                 BOOST_CATCH (...)
514                 {
515                     flag.epoch=uninitialized_flag;
516                     BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
517                     BOOST_RETHROW
518                 }
519                 BOOST_CATCH_END
520                 flag.epoch=--thread_detail::once_global_epoch;
521                 BOOST_VERIFY(!posix::pthread_cond_broadcast(&thread_detail::once_epoch_cv));
522             }
523             else
524             {
525                 while(flag.epoch==being_initialized)
526                 {
527                     BOOST_VERIFY(!posix::pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex));
528                 }
529             }
530         }
531         this_thread_epoch=thread_detail::once_global_epoch;
532     }
533   }
534 
535 #endif
536 
537 }
538 
539 #include <boost/config/abi_suffix.hpp>
540 
541 #endif
542