// Copyright (C) 2007 Anthony Williams // // 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) #define __STDC_CONSTANT_MACROS #include #include #include #include #include #include #include namespace boost { namespace thread_detail { enum flag_states { uninitialized, in_progress, initialized }; typedef boost::atomic< unsigned int > atomic_type #if defined(__GNUC__) __attribute__((may_alias)) #endif ; BOOST_STATIC_ASSERT_MSG(sizeof(once_flag) >= sizeof(atomic_type), "Boost.Thread: unsupported platform"); static pthread_mutex_t once_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t once_cv = PTHREAD_COND_INITIALIZER; BOOST_THREAD_DECL bool enter_once_region(once_flag& flag) BOOST_NOEXCEPT { atomic_type& f = reinterpret_cast< atomic_type& >(flag.storage); if (f.load(memory_order_acquire) != initialized) { while (true) { unsigned int expected = uninitialized; if (f.compare_exchange_strong(expected, in_progress, memory_order_acq_rel, memory_order_acquire)) { // We have set the flag to in_progress return true; } else if (expected == initialized) { // Another thread managed to complete the initialization return false; } else { // Wait until the initialization is complete pthread::pthread_mutex_scoped_lock lk(&once_mutex); BOOST_VERIFY(!pthread_cond_wait(&once_cv, &once_mutex)); } } } else return false; } BOOST_THREAD_DECL void commit_once_region(once_flag& flag) BOOST_NOEXCEPT { atomic_type& f = reinterpret_cast< atomic_type& >(flag.storage); pthread::pthread_mutex_scoped_lock lk(&once_mutex); f.store(initialized, memory_order_release); BOOST_VERIFY(!pthread_cond_broadcast(&once_cv)); } BOOST_THREAD_DECL void rollback_once_region(once_flag& flag) BOOST_NOEXCEPT { atomic_type& f = reinterpret_cast< atomic_type& >(flag.storage); pthread::pthread_mutex_scoped_lock lk(&once_mutex); f.store(uninitialized, memory_order_release); BOOST_VERIFY(!pthread_cond_broadcast(&once_cv)); } } // namespace thread_detail } // namespace boost