PageRenderTime 31ms CodeModel.GetById 18ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/thread/pthread/once.hpp

http://hadesmem.googlecode.com/
C++ Header | 95 lines | 72 code | 14 blank | 9 comment | 2 complexity | 45acd5ebda8e0b6a2a92146b2ad5f1c4 MD5 | raw file
 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 "pthread_mutex_scoped_lock.hpp"
18#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
19#include <boost/cstdint.hpp>
20
21#include <boost/config/abi_prefix.hpp>
22
23namespace boost
24{
25
26    struct once_flag
27    {
28        boost::uintmax_t epoch;
29    };
30
31    namespace detail
32    {
33        BOOST_THREAD_DECL boost::uintmax_t& get_once_per_thread_epoch();
34        BOOST_THREAD_DECL extern boost::uintmax_t once_global_epoch;
35        BOOST_THREAD_DECL extern pthread_mutex_t once_epoch_mutex;
36        BOOST_THREAD_DECL extern pthread_cond_t once_epoch_cv;
37    }
38    
39#define BOOST_ONCE_INITIAL_FLAG_VALUE 0
40#define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE}
41
42
43    // Based on Mike Burrows fast_pthread_once algorithm as described in
44    // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2444.html
45    template<typename Function>
46    void call_once(once_flag& flag,Function f)
47    {
48        static boost::uintmax_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
49        static boost::uintmax_t const being_initialized=uninitialized_flag+1;
50        boost::uintmax_t const epoch=flag.epoch;
51        boost::uintmax_t& this_thread_epoch=detail::get_once_per_thread_epoch();
52        
53        if(epoch<this_thread_epoch)
54        {
55            pthread::pthread_mutex_scoped_lock lk(&detail::once_epoch_mutex);
56
57            while(flag.epoch<=being_initialized)
58            {
59                if(flag.epoch==uninitialized_flag)
60                {
61                    flag.epoch=being_initialized;
62#ifndef BOOST_NO_EXCEPTIONS
63                    try
64                    {
65#endif
66                        pthread::pthread_mutex_scoped_unlock relocker(&detail::once_epoch_mutex);
67                        f();
68#ifndef BOOST_NO_EXCEPTIONS
69                    }
70                    catch(...)
71                    {
72                        flag.epoch=uninitialized_flag;
73                        BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
74                        throw;
75                    }
76#endif
77                    flag.epoch=--detail::once_global_epoch;
78                    BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
79                }
80                else
81                {
82                    while(flag.epoch==being_initialized)
83                    {
84                        BOOST_VERIFY(!pthread_cond_wait(&detail::once_epoch_cv,&detail::once_epoch_mutex));
85                    }
86                }
87            }
88            this_thread_epoch=detail::once_global_epoch;
89        }
90    }
91}
92
93#include <boost/config/abi_suffix.hpp>
94
95#endif