1 // Copyright (c) 2007-2014 Hartmut Kaiser 2 // 3 // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 // 6 // This code has been partially adopted from the Boost.Threads library 7 // 8 // (C) Copyright 2008 Anthony Williams 9 // (C) Copyright 2011-2012 Vicente J. Botet Escriba 10 11 #if !defined(HPX_UTIL_RUNTIME_THREADS_THREAD_SPECIFIC_PTR_MAR_20_2014_0941A320PM) 12 #define HPX_UTIL_RUNTIME_THREADS_THREAD_SPECIFIC_PTR_MAR_20_2014_0941A320PM 13 14 #include <hpx/config.hpp> 15 #include <hpx/runtime/threads/coroutines/detail/tss.hpp> 16 #include <hpx/runtime/threads/thread_data_fwd.hpp> 17 18 #include <memory> 19 20 namespace hpx { namespace threads 21 { 22 /////////////////////////////////////////////////////////////////////////// 23 template <typename T> 24 class thread_specific_ptr 25 { 26 private: 27 typedef coroutines::detail::tss_cleanup_function cleanup_function; 28 29 thread_specific_ptr(thread_specific_ptr&); 30 thread_specific_ptr& operator=(thread_specific_ptr&); 31 32 struct delete_data 33 : coroutines::detail::tss_cleanup_function 34 { operator ()hpx::threads::thread_specific_ptr::delete_data35 void operator()(void* data) 36 { 37 delete static_cast<T*>(data); 38 } 39 }; 40 41 struct run_custom_cleanup_function 42 : coroutines::detail::tss_cleanup_function 43 { run_custom_cleanup_functionhpx::threads::thread_specific_ptr::run_custom_cleanup_function44 explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)): 45 cleanup_function(cleanup_function_) 46 {} 47 operator ()hpx::threads::thread_specific_ptr::run_custom_cleanup_function48 void operator()(void* data) 49 { 50 cleanup_function(static_cast<T*>(data)); 51 } 52 53 void (*cleanup_function)(T*); 54 }; 55 56 std::shared_ptr<cleanup_function> cleanup_; 57 58 public: 59 typedef T element_type; 60 thread_specific_ptr()61 thread_specific_ptr() 62 : cleanup_(std::make_shared<delete_data>()) 63 {} 64 thread_specific_ptr(void (* func_)(T *))65 explicit thread_specific_ptr(void (*func_)(T*)) 66 { 67 if (func_) 68 cleanup_.reset(new run_custom_cleanup_function(func_)); 69 } 70 ~thread_specific_ptr()71 ~thread_specific_ptr() 72 { 73 // clean up data if this type is used locally for one thread 74 if (get_self_ptr()) 75 coroutines::detail::erase_tss_node(this, true); 76 } 77 get() const78 T* get() const 79 { 80 return static_cast<T*>(coroutines::detail::get_tss_data(this)); 81 } 82 operator ->() const83 T* operator->() const 84 { 85 return get(); 86 } 87 operator *() const88 T& operator*() const 89 { 90 return *get(); 91 } 92 release()93 T* release() 94 { 95 T* const temp = get(); 96 coroutines::detail::set_tss_data( 97 this, std::shared_ptr<cleanup_function>()); 98 return temp; 99 } reset(T * new_value=nullptr)100 void reset(T* new_value = nullptr) 101 { 102 T* const current_value = get(); 103 if (current_value != new_value) 104 { 105 coroutines::detail::set_tss_data( 106 this, cleanup_, new_value, true); 107 } 108 } 109 }; 110 }} 111 112 #endif 113