imgtools/imglib/boostlibrary/boost/thread/win32/once.hpp
changeset 0 044383f39525
equal deleted inserted replaced
-1:000000000000 0:044383f39525
       
     1 #ifndef BOOST_THREAD_WIN32_ONCE_HPP
       
     2 #define BOOST_THREAD_WIN32_ONCE_HPP
       
     3 
       
     4 //  once.hpp
       
     5 //
       
     6 //  (C) Copyright 2005-7 Anthony Williams 
       
     7 //  (C) Copyright 2005 John Maddock
       
     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 <cstring>
       
    14 #include <cstddef>
       
    15 #include <boost/assert.hpp>
       
    16 #include <boost/static_assert.hpp>
       
    17 #include <boost/detail/interlocked.hpp>
       
    18 #include <boost/thread/win32/thread_primitives.hpp>
       
    19 #include <boost/thread/win32/interlocked_read.hpp>
       
    20 
       
    21 #include <boost/config/abi_prefix.hpp>
       
    22 
       
    23 #ifdef BOOST_NO_STDC_NAMESPACE
       
    24 namespace std
       
    25 {
       
    26     using ::memcpy;
       
    27     using ::ptrdiff_t;
       
    28 }
       
    29 #endif
       
    30 
       
    31 namespace boost
       
    32 {
       
    33     typedef long once_flag;
       
    34 
       
    35 #define BOOST_ONCE_INIT 0
       
    36 
       
    37     namespace detail
       
    38     {
       
    39         struct win32_mutex_scoped_lock
       
    40         {
       
    41             void* const mutex_handle;
       
    42             explicit win32_mutex_scoped_lock(void* mutex_handle_):
       
    43                 mutex_handle(mutex_handle_)
       
    44             {
       
    45                 BOOST_VERIFY(!win32::WaitForSingleObject(mutex_handle,win32::infinite));
       
    46             }
       
    47             ~win32_mutex_scoped_lock()
       
    48             {
       
    49                 BOOST_VERIFY(win32::ReleaseMutex(mutex_handle)!=0);
       
    50             }
       
    51         private:
       
    52             void operator=(win32_mutex_scoped_lock&);
       
    53         };
       
    54 
       
    55 #ifdef BOOST_NO_ANSI_APIS
       
    56         template <class I>
       
    57         void int_to_string(I p, wchar_t* buf)
       
    58         {
       
    59             for(unsigned i=0; i < sizeof(I)*2; ++i,++buf)
       
    60             {
       
    61                 *buf = L'A' + static_cast<wchar_t>((p >> (i*4)) & 0x0f);
       
    62             }
       
    63             *buf = 0;
       
    64         }
       
    65 #else
       
    66         template <class I>
       
    67         void int_to_string(I p, char* buf)
       
    68         {
       
    69             for(unsigned i=0; i < sizeof(I)*2; ++i,++buf)
       
    70             {
       
    71                 *buf = 'A' + static_cast<char>((p >> (i*4)) & 0x0f);
       
    72             }
       
    73             *buf = 0;
       
    74         }
       
    75 #endif
       
    76 
       
    77         // create a named mutex. It doesn't really matter what this name is
       
    78         // as long as it is unique both to this process, and to the address of "flag":
       
    79         inline void* create_once_mutex(void* flag_address)
       
    80         {
       
    81         
       
    82 #ifdef BOOST_NO_ANSI_APIS
       
    83             typedef wchar_t char_type;
       
    84             static const char_type fixed_mutex_name[]=L"{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
       
    85 #else
       
    86             typedef char char_type;
       
    87             static const char_type fixed_mutex_name[]="{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
       
    88 #endif
       
    89             unsigned const once_mutex_name_fixed_buffer_size=sizeof(fixed_mutex_name)/sizeof(char_type);
       
    90             unsigned const once_mutex_name_fixed_length=once_mutex_name_fixed_buffer_size-1;
       
    91             unsigned const once_mutex_name_length=once_mutex_name_fixed_buffer_size+sizeof(void*)*2+sizeof(unsigned long)*2;
       
    92             char_type mutex_name[once_mutex_name_length];
       
    93             
       
    94             std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name));
       
    95 
       
    96             BOOST_STATIC_ASSERT(sizeof(void*) == sizeof(std::ptrdiff_t));
       
    97             detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address), mutex_name + once_mutex_name_fixed_length);
       
    98             detail::int_to_string(win32::GetCurrentProcessId(), mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2);
       
    99 
       
   100 #ifdef BOOST_NO_ANSI_APIS
       
   101             return win32::CreateMutexW(0, 0, mutex_name);
       
   102 #else
       
   103             return win32::CreateMutexA(0, 0, mutex_name);
       
   104 #endif
       
   105         }
       
   106 
       
   107         
       
   108     }
       
   109     
       
   110 
       
   111     template<typename Function>
       
   112     void call_once(once_flag& flag,Function f)
       
   113     {
       
   114         // Try for a quick win: if the procedure has already been called
       
   115         // just skip through:
       
   116         long const function_complete_flag_value=0xc15730e2;
       
   117 
       
   118         if(::boost::detail::interlocked_read_acquire(&flag)!=function_complete_flag_value)
       
   119         {
       
   120             void* const mutex_handle(::boost::detail::create_once_mutex(&flag));
       
   121             BOOST_ASSERT(mutex_handle);
       
   122             detail::win32::handle_manager const closer(mutex_handle);
       
   123             detail::win32_mutex_scoped_lock const lock(mutex_handle);
       
   124       
       
   125             if(flag!=function_complete_flag_value)
       
   126             {
       
   127                 f();
       
   128                 BOOST_INTERLOCKED_EXCHANGE(&flag,function_complete_flag_value);
       
   129             }
       
   130         }
       
   131     }
       
   132 }
       
   133 
       
   134 #include <boost/config/abi_suffix.hpp>
       
   135 
       
   136 #endif