1 #ifndef BOOST_THREAD_PTHREAD_ONCE_HPP
2 #define BOOST_THREAD_PTHREAD_ONCE_HPP
6 // (C) Copyright 2007-8 Anthony Williams
8 // Distributed under the Boost Software License, Version 1.0. (See
9 // accompanying file LICENSE_1_0.txt or copy at
10 // http://www.boost.org/LICENSE_1_0.txt)
12 #include <boost/thread/detail/config.hpp>
15 #include <boost/assert.hpp>
16 #include "pthread_mutex_scoped_lock.hpp"
17 #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
18 #include <boost/cstdint.hpp>
20 #include <boost/config/abi_prefix.hpp>
27 boost::uintmax_t epoch
;
32 BOOST_THREAD_DECL
boost::uintmax_t& get_once_per_thread_epoch();
33 BOOST_THREAD_DECL
extern boost::uintmax_t once_global_epoch
;
34 BOOST_THREAD_DECL
extern pthread_mutex_t once_epoch_mutex
;
35 BOOST_THREAD_DECL
extern pthread_cond_t once_epoch_cv
;
38 #define BOOST_ONCE_INITIAL_FLAG_VALUE 0
39 #define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE}
42 // Based on Mike Burrows fast_pthread_once algorithm as described in
43 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2444.html
44 template<typename Function
>
45 void call_once(once_flag
& flag
,Function f
)
47 static boost::uintmax_t const uninitialized_flag
=BOOST_ONCE_INITIAL_FLAG_VALUE
;
48 static boost::uintmax_t const being_initialized
=uninitialized_flag
+1;
49 boost::uintmax_t const epoch
=flag
.epoch
;
50 boost::uintmax_t& this_thread_epoch
=detail::get_once_per_thread_epoch();
52 if(epoch
<this_thread_epoch
)
54 pthread::pthread_mutex_scoped_lock
lk(&detail::once_epoch_mutex
);
56 while(flag
.epoch
<=being_initialized
)
58 if(flag
.epoch
==uninitialized_flag
)
60 flag
.epoch
=being_initialized
;
63 pthread::pthread_mutex_scoped_unlock
relocker(&detail::once_epoch_mutex
);
68 flag
.epoch
=uninitialized_flag
;
69 BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv
));
72 flag
.epoch
=--detail::once_global_epoch
;
73 BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv
));
77 while(flag
.epoch
==being_initialized
)
79 BOOST_VERIFY(!pthread_cond_wait(&detail::once_epoch_cv
,&detail::once_epoch_mutex
));
83 this_thread_epoch
=detail::once_global_epoch
;
88 #include <boost/config/abi_suffix.hpp>