imgtools/imglib/boostlibrary/boost/thread/pthread/once.hpp
changeset 0 044383f39525
equal deleted inserted replaced
-1:000000000000 0:044383f39525
       
     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 
       
    14 #include <pthread.h>
       
    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>
       
    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                     try
       
    62                     {
       
    63                         pthread::pthread_mutex_scoped_unlock relocker(&detail::once_epoch_mutex);
       
    64                         f();
       
    65                     }
       
    66                     catch(...)
       
    67                     {
       
    68                         flag.epoch=uninitialized_flag;
       
    69                         BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
       
    70                         throw;
       
    71                     }
       
    72                     flag.epoch=--detail::once_global_epoch;
       
    73                     BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
       
    74                 }
       
    75                 else
       
    76                 {
       
    77                     while(flag.epoch==being_initialized)
       
    78                     {
       
    79                         BOOST_VERIFY(!pthread_cond_wait(&detail::once_epoch_cv,&detail::once_epoch_mutex));
       
    80                     }
       
    81                 }
       
    82             }
       
    83             this_thread_epoch=detail::once_global_epoch;
       
    84         }
       
    85     }
       
    86 }
       
    87 
       
    88 #include <boost/config/abi_suffix.hpp>
       
    89 
       
    90 #endif