os/ossrv/ossrv_pub/boost_apis/boost/thread/tss.hpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (C) 2001-2003 William E. Kempf
     2 // Copyright (C) 2006 Roland Schwarz
     3 //
     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)
     6 
     7 #ifndef BOOST_TSS_WEK070601_HPP
     8 #define BOOST_TSS_WEK070601_HPP
     9 
    10 #include <boost/thread/detail/config.hpp>
    11 
    12 #include <boost/utility.hpp>
    13 #include <boost/function.hpp>
    14 #include <boost/thread/exceptions.hpp>
    15 
    16 #if defined(BOOST_HAS_PTHREADS)
    17 #   include <pthread.h>
    18 #elif defined(BOOST_HAS_MPTASKS)
    19 #   include <Multiprocessing.h>
    20 #endif
    21 
    22 namespace boost {
    23 
    24 // disable warnings about non dll import
    25 // see: http://www.boost.org/more/separate_compilation.html#dlls
    26 #ifdef BOOST_MSVC
    27 #   pragma warning(push)
    28 #   pragma warning(disable: 4251 4231 4660 4275)
    29 #endif
    30 
    31 namespace detail {
    32 
    33 class BOOST_THREAD_DECL tss : private noncopyable
    34 {
    35 public:
    36     tss(boost::function1<void, void*>* pcleanup) {
    37         if (pcleanup == 0) throw boost::thread_resource_error();
    38         try
    39         {
    40             init(pcleanup);
    41         }
    42         catch (...)
    43         {
    44             delete pcleanup;
    45             throw boost::thread_resource_error();
    46         }
    47     }
    48 
    49     ~tss();
    50     void* get() const;
    51     void set(void* value);
    52     void cleanup(void* p);
    53 
    54 private:
    55     unsigned int m_slot; //This is a "pseudo-slot", not a native slot
    56 
    57     void init(boost::function1<void, void*>* pcleanup);
    58 };
    59 
    60 #if defined(BOOST_HAS_MPTASKS)
    61 void thread_cleanup();
    62 #endif
    63 
    64 template <typename T>
    65 struct tss_adapter
    66 {
    67     template <typename F>
    68     tss_adapter(const F& cleanup) : m_cleanup(cleanup) { }
    69     void operator()(void* p) { m_cleanup(static_cast<T*>(p)); }
    70     boost::function1<void, T*> m_cleanup;
    71 };
    72 
    73 } // namespace detail
    74 
    75 template <typename T>
    76 class thread_specific_ptr : private noncopyable
    77 {
    78 public:
    79     thread_specific_ptr()
    80         : m_tss(new boost::function1<void, void*>(
    81                     boost::detail::tss_adapter<T>(
    82                         &thread_specific_ptr<T>::cleanup)))
    83     {
    84     }
    85     thread_specific_ptr(void (*clean)(T*))
    86         : m_tss(new boost::function1<void, void*>(
    87                     boost::detail::tss_adapter<T>(clean)))
    88     {
    89     }
    90     ~thread_specific_ptr() { reset(); }
    91 
    92     T* get() const { return static_cast<T*>(m_tss.get()); }
    93     T* operator->() const { return get(); }
    94     T& operator*() const { return *get(); }
    95     T* release() { T* temp = get(); if (temp) m_tss.set(0); return temp; }
    96     void reset(T* p=0)
    97     {
    98         T* cur = get();
    99         if (cur == p) return;
   100         m_tss.set(p);
   101         if (cur) m_tss.cleanup(cur);
   102     }
   103 
   104 private:
   105     static void cleanup(T* p) { delete p; }
   106     detail::tss m_tss;
   107 };
   108 
   109 #ifdef BOOST_MSVC
   110 #   pragma warning(pop)
   111 #endif
   112 
   113 } // namespace boost
   114 
   115 #endif //BOOST_TSS_WEK070601_HPP
   116 
   117 // Change Log:
   118 //   6 Jun 01  
   119 //      WEKEMPF Initial version.
   120 //  30 May 02  WEKEMPF 
   121 //      Added interface to set specific cleanup handlers.
   122 //      Removed TLS slot limits from most implementations.
   123 //  22 Mar 04 GlassfordM for WEKEMPF
   124 //      Fixed: thread_specific_ptr::reset() doesn't check error returned
   125 //          by tss::set(); tss::set() now throws if it fails.
   126 //      Fixed: calling thread_specific_ptr::reset() or 
   127 //          thread_specific_ptr::release() causes double-delete: once on
   128 //          reset()/release() and once on ~thread_specific_ptr().