]> rtime.felk.cvut.cz Git - eurobot/public.git/blob - src/boost/boost/thread/pthread/once.hpp
Add subset of boost library headers needed for compilation on PowerPC
[eurobot/public.git] / src / boost / boost / thread / pthread / once.hpp
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 //
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)
11
12 #include <boost/thread/detail/config.hpp>
13 #include <boost/config.hpp>
14
15 #include <pthread.h>
16 #include <boost/assert.hpp>
17 #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
18 #include <boost/cstdint.hpp>
19
20 #include <boost/config/abi_prefix.hpp>
21
22 namespace boost
23 {
24
25     struct once_flag
26     {
27         boost::uintmax_t epoch;
28     };
29
30     namespace detail
31     {
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;
36     }
37
38 #define BOOST_ONCE_INITIAL_FLAG_VALUE 0
39 #define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE}
40
41
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)
46     {
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();
51
52         if(epoch<this_thread_epoch)
53         {
54             pthread::pthread_mutex_scoped_lock lk(&detail::once_epoch_mutex);
55
56             while(flag.epoch<=being_initialized)
57             {
58                 if(flag.epoch==uninitialized_flag)
59                 {
60                     flag.epoch=being_initialized;
61 #ifndef BOOST_NO_EXCEPTIONS
62                     try
63                     {
64 #endif
65                         pthread::pthread_mutex_scoped_unlock relocker(&detail::once_epoch_mutex);
66                         f();
67 #ifndef BOOST_NO_EXCEPTIONS
68                     }
69                     catch(...)
70                     {
71                         flag.epoch=uninitialized_flag;
72                         BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
73                         throw;
74                     }
75 #endif
76                     flag.epoch=--detail::once_global_epoch;
77                     BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
78                 }
79                 else
80                 {
81                     while(flag.epoch==being_initialized)
82                     {
83                         BOOST_VERIFY(!pthread_cond_wait(&detail::once_epoch_cv,&detail::once_epoch_mutex));
84                     }
85                 }
86             }
87             this_thread_epoch=detail::once_global_epoch;
88         }
89     }
90 }
91
92 #include <boost/config/abi_suffix.hpp>
93
94 #endif