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
25namespace Poco {
26
27
28class Foundation_API TLSAbstractSlot
29 /// This is the base class for all objects
30 /// that the ThreadLocalStorage class manages.
31{
32public:
33 TLSAbstractSlot();
34 virtual ~TLSAbstractSlot();
35};
36
37
38template <class C>
39class 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{
45public:
46 TLSSlot():
47 _value()
48 {
49 }
50
51 ~TLSSlot()
52 {
53 }
54
55 C& value()
56 {
57 return _value;
58 }
59
60private:
61 TLSSlot(const TLSSlot&);
62 TLSSlot& operator = (const TLSSlot&);
63
64 C _value;
65};
66
67
68class 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{
73public:
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
91private:
92 typedef std::map<const void*, TLSAbstractSlot*> TLSMap;
93
94 TLSMap _map;
95
96 friend class Thread;
97};
98
99
100template <class C>
101class 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
117public:
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
148private:
149 ThreadLocal(const ThreadLocal&);
150 ThreadLocal& operator = (const ThreadLocal&);
151};
152
153
154} // namespace Poco
155
156
157#endif // Foundation_ThreadLocal_INCLUDED
158