1 | // |
2 | // ThreadLocal.h |
3 | // |
4 | // Library: Foundation |
5 | // Package: Threading |
6 | // Module: Thread |
7 | // |
8 | // Definition of the ThreadLocal template and related classes. |
9 | // |
10 | // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. |
11 | // and Contributors. |
12 | // |
13 | // SPDX-License-Identifier: BSL-1.0 |
14 | // |
15 | |
16 | |
17 | #ifndef Foundation_ThreadLocal_INCLUDED |
18 | #define Foundation_ThreadLocal_INCLUDED |
19 | |
20 | |
21 | #include "Poco/Foundation.h" |
22 | #include <map> |
23 | |
24 | |
25 | namespace Poco { |
26 | |
27 | |
28 | class Foundation_API TLSAbstractSlot |
29 | /// This is the base class for all objects |
30 | /// that the ThreadLocalStorage class manages. |
31 | { |
32 | public: |
33 | TLSAbstractSlot(); |
34 | virtual ~TLSAbstractSlot(); |
35 | }; |
36 | |
37 | |
38 | template <class C> |
39 | class TLSSlot: public TLSAbstractSlot |
40 | /// The Slot template wraps another class |
41 | /// so that it can be stored in a ThreadLocalStorage |
42 | /// object. This class is used internally, and you |
43 | /// must not create instances of it yourself. |
44 | { |
45 | public: |
46 | TLSSlot(): |
47 | _value() |
48 | { |
49 | } |
50 | |
51 | ~TLSSlot() |
52 | { |
53 | } |
54 | |
55 | C& value() |
56 | { |
57 | return _value; |
58 | } |
59 | |
60 | private: |
61 | TLSSlot(const TLSSlot&); |
62 | TLSSlot& operator = (const TLSSlot&); |
63 | |
64 | C _value; |
65 | }; |
66 | |
67 | |
68 | class Foundation_API ThreadLocalStorage |
69 | /// This class manages the local storage for each thread. |
70 | /// Never use this class directly, always use the |
71 | /// ThreadLocal template for managing thread local storage. |
72 | { |
73 | public: |
74 | ThreadLocalStorage(); |
75 | /// Creates the TLS. |
76 | |
77 | ~ThreadLocalStorage(); |
78 | /// Deletes the TLS. |
79 | |
80 | TLSAbstractSlot*& get(const void* key); |
81 | /// Returns the slot for the given key. |
82 | |
83 | static ThreadLocalStorage& current(); |
84 | /// Returns the TLS object for the current thread |
85 | /// (which may also be the main thread). |
86 | |
87 | static void clear(); |
88 | /// Clears the current thread's TLS object. |
89 | /// Does nothing in the main thread. |
90 | |
91 | private: |
92 | typedef std::map<const void*, TLSAbstractSlot*> TLSMap; |
93 | |
94 | TLSMap _map; |
95 | |
96 | friend class Thread; |
97 | }; |
98 | |
99 | |
100 | template <class C> |
101 | class ThreadLocal |
102 | /// This template is used to declare type safe thread |
103 | /// local variables. It can basically be used like |
104 | /// a smart pointer class with the special feature |
105 | /// that it references a different object |
106 | /// in every thread. The underlying object will |
107 | /// be created when it is referenced for the first |
108 | /// time. |
109 | /// See the NestedDiagnosticContext class for an |
110 | /// example how to use this template. |
111 | /// Every thread only has access to its own |
112 | /// thread local data. There is no way for a thread |
113 | /// to access another thread's local data. |
114 | { |
115 | typedef TLSSlot<C> Slot; |
116 | |
117 | public: |
118 | ThreadLocal() |
119 | { |
120 | } |
121 | |
122 | ~ThreadLocal() |
123 | { |
124 | } |
125 | |
126 | C* operator -> () |
127 | { |
128 | return &get(); |
129 | } |
130 | |
131 | C& operator * () |
132 | /// "Dereferences" the smart pointer and returns a reference |
133 | /// to the underlying data object. The reference can be used |
134 | /// to modify the object. |
135 | { |
136 | return get(); |
137 | } |
138 | |
139 | C& get() |
140 | /// Returns a reference to the underlying data object. |
141 | /// The reference can be used to modify the object. |
142 | { |
143 | TLSAbstractSlot*& p = ThreadLocalStorage::current().get(this); |
144 | if (!p) p = new Slot; |
145 | return static_cast<Slot*>(p)->value(); |
146 | } |
147 | |
148 | private: |
149 | ThreadLocal(const ThreadLocal&); |
150 | ThreadLocal& operator = (const ThreadLocal&); |
151 | }; |
152 | |
153 | |
154 | } // namespace Poco |
155 | |
156 | |
157 | #endif // Foundation_ThreadLocal_INCLUDED |
158 | |