Back to home page

EIC code displayed by LXR

 
 

    


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 //  once.hpp
0005 //
0006 //  (C) Copyright 2013 Andrey Semashev
0007 //  (C) Copyright 2013 Vicente J. Botet Escriba
0008 //
0009 //  Distributed under the Boost Software License, Version 1.0. (See
0010 //  accompanying file LICENSE_1_0.txt or copy at
0011 //  http://www.boost.org/LICENSE_1_0.txt)
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     // All tested integer types are not atomic, the spinlock pool will be used
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       //return reinterpret_cast< atomic_type& >(flag.storage);
0080       return flag.storage;
0081     }
0082   }
0083 
0084 #else // BOOST_THREAD_PROVIDES_ONCE_CXX11
0085   struct once_flag
0086   {
0087     // The thread_detail::atomic_int_type storage is marked
0088     // with this attribute in order to let the compiler know that it will alias this member
0089     // and silence compilation warnings.
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 // BOOST_THREAD_PROVIDES_ONCE_CXX11
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 // __SUNPRO_CC
0306 
0307 #endif
0308 }
0309 
0310 #include <boost/config/abi_suffix.hpp>
0311 
0312 #endif
0313