File indexing completed on 2024-11-15 09:32:38
0001 #ifndef BOOST_THREAD_PTHREAD_ONCE_ATOMIC_HPP
0002 #define BOOST_THREAD_PTHREAD_ONCE_ATOMIC_HPP
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <boost/thread/detail/config.hpp>
0014
0015 #include <boost/cstdint.hpp>
0016 #include <boost/thread/detail/move.hpp>
0017 #include <boost/thread/detail/invoke.hpp>
0018 #include <boost/core/no_exceptions_support.hpp>
0019 #include <boost/bind/bind.hpp>
0020 #include <boost/atomic.hpp>
0021
0022 #include <boost/config/abi_prefix.hpp>
0023
0024 namespace boost
0025 {
0026
0027 struct once_flag;
0028
0029 namespace thread_detail
0030 {
0031
0032 #if BOOST_ATOMIC_INT_LOCK_FREE == 2
0033 typedef unsigned int atomic_int_type;
0034 #elif BOOST_ATOMIC_SHORT_LOCK_FREE == 2
0035 typedef unsigned short atomic_int_type;
0036 #elif BOOST_ATOMIC_CHAR_LOCK_FREE == 2
0037 typedef unsigned char atomic_int_type;
0038 #elif BOOST_ATOMIC_LONG_LOCK_FREE == 2
0039 typedef unsigned long atomic_int_type;
0040 #elif defined(BOOST_HAS_LONG_LONG) && BOOST_ATOMIC_LLONG_LOCK_FREE == 2
0041 typedef ulong_long_type atomic_int_type;
0042 #else
0043
0044 typedef unsigned int atomic_int_type;
0045 #endif
0046
0047 typedef boost::atomic<atomic_int_type> atomic_type;
0048
0049 BOOST_THREAD_DECL bool enter_once_region(once_flag& flag) BOOST_NOEXCEPT;
0050 BOOST_THREAD_DECL void commit_once_region(once_flag& flag) BOOST_NOEXCEPT;
0051 BOOST_THREAD_DECL void rollback_once_region(once_flag& flag) BOOST_NOEXCEPT;
0052 inline atomic_type& get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT;
0053 }
0054
0055 #ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
0056
0057 struct once_flag
0058 {
0059 BOOST_THREAD_NO_COPYABLE(once_flag)
0060 BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT : storage(0)
0061 {
0062 }
0063
0064 private:
0065 thread_detail::atomic_type storage;
0066
0067 friend BOOST_THREAD_DECL bool thread_detail::enter_once_region(once_flag& flag) BOOST_NOEXCEPT;
0068 friend BOOST_THREAD_DECL void thread_detail::commit_once_region(once_flag& flag) BOOST_NOEXCEPT;
0069 friend BOOST_THREAD_DECL void thread_detail::rollback_once_region(once_flag& flag) BOOST_NOEXCEPT;
0070 friend thread_detail::atomic_type& thread_detail::get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT;
0071 };
0072
0073 #define BOOST_ONCE_INIT boost::once_flag()
0074
0075 namespace thread_detail
0076 {
0077 inline atomic_type& get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT
0078 {
0079
0080 return flag.storage;
0081 }
0082 }
0083
0084 #else
0085 struct once_flag
0086 {
0087
0088
0089
0090 BOOST_THREAD_ATTRIBUTE_MAY_ALIAS thread_detail::atomic_int_type storage;
0091 };
0092
0093 #define BOOST_ONCE_INIT {0}
0094
0095 namespace thread_detail
0096 {
0097 inline atomic_type& get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT
0098 {
0099 return reinterpret_cast< atomic_type& >(flag.storage);
0100 }
0101
0102 }
0103
0104 #endif
0105
0106 #if defined BOOST_THREAD_PROVIDES_INVOKE
0107 #define BOOST_THREAD_INVOKE_RET_VOID detail::invoke
0108 #define BOOST_THREAD_INVOKE_RET_VOID_CALL
0109 #elif defined BOOST_THREAD_PROVIDES_INVOKE_RET
0110 #define BOOST_THREAD_INVOKE_RET_VOID detail::invoke<void>
0111 #define BOOST_THREAD_INVOKE_RET_VOID_CALL
0112 #else
0113 #define BOOST_THREAD_INVOKE_RET_VOID boost::bind
0114 #define BOOST_THREAD_INVOKE_RET_VOID_CALL ()
0115 #endif
0116
0117
0118 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0119
0120 template<typename Function, class ...ArgTypes>
0121 inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args)
0122 {
0123 if (thread_detail::enter_once_region(flag))
0124 {
0125 BOOST_TRY
0126 {
0127 BOOST_THREAD_INVOKE_RET_VOID(
0128 thread_detail::decay_copy(boost::forward<Function>(f)),
0129 thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
0130 ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
0131 }
0132 BOOST_CATCH (...)
0133 {
0134 thread_detail::rollback_once_region(flag);
0135 BOOST_RETHROW
0136 }
0137 BOOST_CATCH_END
0138 thread_detail::commit_once_region(flag);
0139 }
0140 }
0141 #else
0142 template<typename Function>
0143 inline void call_once(once_flag& flag, Function f)
0144 {
0145 if (thread_detail::enter_once_region(flag))
0146 {
0147 BOOST_TRY
0148 {
0149 f();
0150 }
0151 BOOST_CATCH (...)
0152 {
0153 thread_detail::rollback_once_region(flag);
0154 BOOST_RETHROW
0155 }
0156 BOOST_CATCH_END
0157 thread_detail::commit_once_region(flag);
0158 }
0159 }
0160
0161 template<typename Function, typename T1>
0162 inline void call_once(once_flag& flag, Function f, T1 p1)
0163 {
0164 if (thread_detail::enter_once_region(flag))
0165 {
0166 BOOST_TRY
0167 {
0168 BOOST_THREAD_INVOKE_RET_VOID(f, p1) BOOST_THREAD_INVOKE_RET_VOID_CALL;
0169 }
0170 BOOST_CATCH (...)
0171 {
0172 thread_detail::rollback_once_region(flag);
0173 BOOST_RETHROW
0174 }
0175 BOOST_CATCH_END
0176 thread_detail::commit_once_region(flag);
0177 }
0178 }
0179
0180 template<typename Function, typename T1, typename T2>
0181 inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2)
0182 {
0183 if (thread_detail::enter_once_region(flag))
0184 {
0185 BOOST_TRY
0186 {
0187 BOOST_THREAD_INVOKE_RET_VOID(f, p1, p2) BOOST_THREAD_INVOKE_RET_VOID_CALL;
0188 }
0189 BOOST_CATCH (...)
0190 {
0191 thread_detail::rollback_once_region(flag);
0192 BOOST_RETHROW
0193 }
0194 BOOST_CATCH_END
0195 thread_detail::commit_once_region(flag);
0196 }
0197 }
0198
0199 template<typename Function, typename T1, typename T2, typename T3>
0200 inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3)
0201 {
0202 if (thread_detail::enter_once_region(flag))
0203 {
0204 BOOST_TRY
0205 {
0206 BOOST_THREAD_INVOKE_RET_VOID(f, p1, p2, p3) BOOST_THREAD_INVOKE_RET_VOID_CALL;
0207 }
0208 BOOST_CATCH (...)
0209 {
0210 thread_detail::rollback_once_region(flag);
0211 BOOST_RETHROW
0212 }
0213 BOOST_CATCH_END
0214 thread_detail::commit_once_region(flag);
0215 }
0216 }
0217 #if !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130))
0218 template<typename Function>
0219 inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f)
0220 {
0221 if (thread_detail::enter_once_region(flag))
0222 {
0223 BOOST_TRY
0224 {
0225 f();
0226 }
0227 BOOST_CATCH (...)
0228 {
0229 thread_detail::rollback_once_region(flag);
0230 BOOST_RETHROW
0231 }
0232 BOOST_CATCH_END
0233 thread_detail::commit_once_region(flag);
0234 }
0235 }
0236
0237 template<typename Function, typename T1>
0238 inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1)
0239 {
0240 if (thread_detail::enter_once_region(flag))
0241 {
0242 BOOST_TRY
0243 {
0244 BOOST_THREAD_INVOKE_RET_VOID(
0245 thread_detail::decay_copy(boost::forward<Function>(f)),
0246 thread_detail::decay_copy(boost::forward<T1>(p1))
0247 ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
0248 }
0249 BOOST_CATCH (...)
0250 {
0251 thread_detail::rollback_once_region(flag);
0252 BOOST_RETHROW
0253 }
0254 BOOST_CATCH_END
0255 thread_detail::commit_once_region(flag);
0256 }
0257 }
0258 template<typename Function, typename T1, typename T2>
0259 inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2)
0260 {
0261 if (thread_detail::enter_once_region(flag))
0262 {
0263 BOOST_TRY
0264 {
0265 BOOST_THREAD_INVOKE_RET_VOID(
0266 thread_detail::decay_copy(boost::forward<Function>(f)),
0267 thread_detail::decay_copy(boost::forward<T1>(p1)),
0268 thread_detail::decay_copy(boost::forward<T1>(p2))
0269 ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
0270 }
0271 BOOST_CATCH (...)
0272 {
0273 thread_detail::rollback_once_region(flag);
0274 BOOST_RETHROW
0275 }
0276 BOOST_CATCH_END
0277 thread_detail::commit_once_region(flag);
0278 }
0279 }
0280 template<typename Function, typename T1, typename T2, typename T3>
0281 inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2, BOOST_THREAD_RV_REF(T3) p3)
0282 {
0283 if (thread_detail::enter_once_region(flag))
0284 {
0285 BOOST_TRY
0286 {
0287 BOOST_THREAD_INVOKE_RET_VOID(
0288 thread_detail::decay_copy(boost::forward<Function>(f)),
0289 thread_detail::decay_copy(boost::forward<T1>(p1)),
0290 thread_detail::decay_copy(boost::forward<T1>(p2)),
0291 thread_detail::decay_copy(boost::forward<T1>(p3))
0292 ) BOOST_THREAD_INVOKE_RET_VOID_CALL;
0293
0294 }
0295 BOOST_CATCH (...)
0296 {
0297 thread_detail::rollback_once_region(flag);
0298 BOOST_RETHROW
0299 }
0300 BOOST_CATCH_END
0301 thread_detail::commit_once_region(flag);
0302 }
0303 }
0304
0305 #endif
0306
0307 #endif
0308 }
0309
0310 #include <boost/config/abi_suffix.hpp>
0311
0312 #endif
0313