1 // (C) Copyright 2013 Andrey Semashev
2 // (C) Copyright 2013 Vicente J. Botet Escriba
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //#define __STDC_CONSTANT_MACROS
8 #include <boost/thread/detail/config.hpp>
9 #include <boost/thread/once.hpp>
10 #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
11 #include <boost/assert.hpp>
12 #include <boost/static_assert.hpp>
13 #include <boost/atomic.hpp>
14 #include <boost/memory_order.hpp>
19 namespace thread_detail
24 uninitialized
, in_progress
, initialized
28 #ifndef BOOST_THREAD_PROVIDES_ONCE_CXX11
29 BOOST_STATIC_ASSERT_MSG(sizeof(atomic_int_type
) == sizeof(atomic_type
), "Boost.Thread: unsupported platform");
32 static pthread_mutex_t once_mutex
= PTHREAD_MUTEX_INITIALIZER
;
33 static pthread_cond_t once_cv
= PTHREAD_COND_INITIALIZER
;
35 BOOST_THREAD_DECL
bool enter_once_region(once_flag
& flag
) BOOST_NOEXCEPT
37 atomic_type
& f
= get_atomic_storage(flag
);
38 if (f
.load(memory_order_acquire
) != initialized
)
40 pthread::pthread_mutex_scoped_lock
lk(&once_mutex
);
41 if (f
.load(memory_order_acquire
) != initialized
)
45 atomic_int_type expected
= uninitialized
;
46 if (f
.compare_exchange_strong(expected
, in_progress
, memory_order_acq_rel
, memory_order_acquire
))
48 // We have set the flag to in_progress
51 else if (expected
== initialized
)
53 // Another thread managed to complete the initialization
58 // Wait until the initialization is complete
59 //pthread::pthread_mutex_scoped_lock lk(&once_mutex);
60 BOOST_VERIFY(!pthread_cond_wait(&once_cv
, &once_mutex
));
68 BOOST_THREAD_DECL
void commit_once_region(once_flag
& flag
) BOOST_NOEXCEPT
70 atomic_type
& f
= get_atomic_storage(flag
);
72 pthread::pthread_mutex_scoped_lock
lk(&once_mutex
);
73 f
.store(initialized
, memory_order_release
);
75 BOOST_VERIFY(!pthread_cond_broadcast(&once_cv
));
78 BOOST_THREAD_DECL
void rollback_once_region(once_flag
& flag
) BOOST_NOEXCEPT
80 atomic_type
& f
= get_atomic_storage(flag
);
82 pthread::pthread_mutex_scoped_lock
lk(&once_mutex
);
83 f
.store(uninitialized
, memory_order_release
);
85 BOOST_VERIFY(!pthread_cond_broadcast(&once_cv
));
88 } // namespace thread_detail