diff options
Diffstat (limited to '3rdParty/Boost/boost/thread/win32/once.hpp')
-rw-r--r-- | 3rdParty/Boost/boost/thread/win32/once.hpp | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/3rdParty/Boost/boost/thread/win32/once.hpp b/3rdParty/Boost/boost/thread/win32/once.hpp new file mode 100644 index 0000000..a6fcc94 --- /dev/null +++ b/3rdParty/Boost/boost/thread/win32/once.hpp @@ -0,0 +1,136 @@ +#ifndef BOOST_THREAD_WIN32_ONCE_HPP +#define BOOST_THREAD_WIN32_ONCE_HPP + +// once.hpp +// +// (C) Copyright 2005-7 Anthony Williams +// (C) Copyright 2005 John Maddock +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include <cstring> +#include <cstddef> +#include <boost/assert.hpp> +#include <boost/static_assert.hpp> +#include <boost/detail/interlocked.hpp> +#include <boost/thread/win32/thread_primitives.hpp> +#include <boost/thread/win32/interlocked_read.hpp> + +#include <boost/config/abi_prefix.hpp> + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std +{ + using ::memcpy; + using ::ptrdiff_t; +} +#endif + +namespace boost +{ + typedef long once_flag; + +#define BOOST_ONCE_INIT 0 + + namespace detail + { + struct win32_mutex_scoped_lock + { + void* const mutex_handle; + explicit win32_mutex_scoped_lock(void* mutex_handle_): + mutex_handle(mutex_handle_) + { + BOOST_VERIFY(!win32::WaitForSingleObject(mutex_handle,win32::infinite)); + } + ~win32_mutex_scoped_lock() + { + BOOST_VERIFY(win32::ReleaseMutex(mutex_handle)!=0); + } + private: + void operator=(win32_mutex_scoped_lock&); + }; + +#ifdef BOOST_NO_ANSI_APIS + template <class I> + void int_to_string(I p, wchar_t* buf) + { + for(unsigned i=0; i < sizeof(I)*2; ++i,++buf) + { + *buf = L'A' + static_cast<wchar_t>((p >> (i*4)) & 0x0f); + } + *buf = 0; + } +#else + template <class I> + void int_to_string(I p, char* buf) + { + for(unsigned i=0; i < sizeof(I)*2; ++i,++buf) + { + *buf = 'A' + static_cast<char>((p >> (i*4)) & 0x0f); + } + *buf = 0; + } +#endif + + // create a named mutex. It doesn't really matter what this name is + // as long as it is unique both to this process, and to the address of "flag": + inline void* create_once_mutex(void* flag_address) + { + +#ifdef BOOST_NO_ANSI_APIS + typedef wchar_t char_type; + static const char_type fixed_mutex_name[]=L"{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag"; +#else + typedef char char_type; + static const char_type fixed_mutex_name[]="{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag"; +#endif + unsigned const once_mutex_name_fixed_buffer_size=sizeof(fixed_mutex_name)/sizeof(char_type); + unsigned const once_mutex_name_fixed_length=once_mutex_name_fixed_buffer_size-1; + unsigned const once_mutex_name_length=once_mutex_name_fixed_buffer_size+sizeof(void*)*2+sizeof(unsigned long)*2; + char_type mutex_name[once_mutex_name_length]; + + std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name)); + + BOOST_STATIC_ASSERT(sizeof(void*) == sizeof(std::ptrdiff_t)); + detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address), mutex_name + once_mutex_name_fixed_length); + detail::int_to_string(win32::GetCurrentProcessId(), mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2); + +#ifdef BOOST_NO_ANSI_APIS + return win32::CreateMutexW(0, 0, mutex_name); +#else + return win32::CreateMutexA(0, 0, mutex_name); +#endif + } + + + } + + + template<typename Function> + void call_once(once_flag& flag,Function f) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + long const function_complete_flag_value=0xc15730e2; + + if(::boost::detail::interlocked_read_acquire(&flag)!=function_complete_flag_value) + { + void* const mutex_handle(::boost::detail::create_once_mutex(&flag)); + BOOST_ASSERT(mutex_handle); + detail::win32::handle_manager const closer(mutex_handle); + detail::win32_mutex_scoped_lock const lock(mutex_handle); + + if(flag!=function_complete_flag_value) + { + f(); + BOOST_INTERLOCKED_EXCHANGE(&flag,function_complete_flag_value); + } + } + } +} + +#include <boost/config/abi_suffix.hpp> + +#endif |