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