sl@0: // Copyright (C) 2001-2003 William E. Kempf sl@0: // Copyright (C) 2006 Roland Schwarz sl@0: // sl@0: // Distributed under the Boost Software License, Version 1.0. (See accompanying sl@0: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) sl@0: sl@0: #ifndef BOOST_TSS_WEK070601_HPP sl@0: #define BOOST_TSS_WEK070601_HPP sl@0: sl@0: #include sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #if defined(BOOST_HAS_PTHREADS) sl@0: # include sl@0: #elif defined(BOOST_HAS_MPTASKS) sl@0: # include sl@0: #endif sl@0: sl@0: namespace boost { sl@0: sl@0: // disable warnings about non dll import sl@0: // see: http://www.boost.org/more/separate_compilation.html#dlls sl@0: #ifdef BOOST_MSVC sl@0: # pragma warning(push) sl@0: # pragma warning(disable: 4251 4231 4660 4275) sl@0: #endif sl@0: sl@0: namespace detail { sl@0: sl@0: class BOOST_THREAD_DECL tss : private noncopyable sl@0: { sl@0: public: sl@0: tss(boost::function1* pcleanup) { sl@0: if (pcleanup == 0) throw boost::thread_resource_error(); sl@0: try sl@0: { sl@0: init(pcleanup); sl@0: } sl@0: catch (...) sl@0: { sl@0: delete pcleanup; sl@0: throw boost::thread_resource_error(); sl@0: } sl@0: } sl@0: sl@0: ~tss(); sl@0: void* get() const; sl@0: void set(void* value); sl@0: void cleanup(void* p); sl@0: sl@0: private: sl@0: unsigned int m_slot; //This is a "pseudo-slot", not a native slot sl@0: sl@0: void init(boost::function1* pcleanup); sl@0: }; sl@0: sl@0: #if defined(BOOST_HAS_MPTASKS) sl@0: void thread_cleanup(); sl@0: #endif sl@0: sl@0: template sl@0: struct tss_adapter sl@0: { sl@0: template sl@0: tss_adapter(const F& cleanup) : m_cleanup(cleanup) { } sl@0: void operator()(void* p) { m_cleanup(static_cast(p)); } sl@0: boost::function1 m_cleanup; sl@0: }; sl@0: sl@0: } // namespace detail sl@0: sl@0: template sl@0: class thread_specific_ptr : private noncopyable sl@0: { sl@0: public: sl@0: thread_specific_ptr() sl@0: : m_tss(new boost::function1( sl@0: boost::detail::tss_adapter( sl@0: &thread_specific_ptr::cleanup))) sl@0: { sl@0: } sl@0: thread_specific_ptr(void (*clean)(T*)) sl@0: : m_tss(new boost::function1( sl@0: boost::detail::tss_adapter(clean))) sl@0: { sl@0: } sl@0: ~thread_specific_ptr() { reset(); } sl@0: sl@0: T* get() const { return static_cast(m_tss.get()); } sl@0: T* operator->() const { return get(); } sl@0: T& operator*() const { return *get(); } sl@0: T* release() { T* temp = get(); if (temp) m_tss.set(0); return temp; } sl@0: void reset(T* p=0) sl@0: { sl@0: T* cur = get(); sl@0: if (cur == p) return; sl@0: m_tss.set(p); sl@0: if (cur) m_tss.cleanup(cur); sl@0: } sl@0: sl@0: private: sl@0: static void cleanup(T* p) { delete p; } sl@0: detail::tss m_tss; sl@0: }; sl@0: sl@0: #ifdef BOOST_MSVC sl@0: # pragma warning(pop) sl@0: #endif sl@0: sl@0: } // namespace boost sl@0: sl@0: #endif //BOOST_TSS_WEK070601_HPP sl@0: sl@0: // Change Log: sl@0: // 6 Jun 01 sl@0: // WEKEMPF Initial version. sl@0: // 30 May 02 WEKEMPF sl@0: // Added interface to set specific cleanup handlers. sl@0: // Removed TLS slot limits from most implementations. sl@0: // 22 Mar 04 GlassfordM for WEKEMPF sl@0: // Fixed: thread_specific_ptr::reset() doesn't check error returned sl@0: // by tss::set(); tss::set() now throws if it fails. sl@0: // Fixed: calling thread_specific_ptr::reset() or sl@0: // thread_specific_ptr::release() causes double-delete: once on sl@0: // reset()/release() and once on ~thread_specific_ptr().