BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslmt_threadlocalvariable.h
Go to the documentation of this file.
1/// @file bslmt_threadlocalvariable.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslmt_threadlocalvariable.h -*-C++-*-
8#ifndef INCLUDED_BSLMT_THREADLOCALVARIABLE
9#define INCLUDED_BSLMT_THREADLOCALVARIABLE
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslmt_threadlocalvariable bslmt_threadlocalvariable
15/// @brief Provide a macro to declare a thread-local variable.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslmt
19/// @{
20/// @addtogroup bslmt_threadlocalvariable
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslmt_threadlocalvariable-purpose"> Purpose</a>
25/// * <a href="#bslmt_threadlocalvariable-macros"> Macros </a>
26/// * <a href="#bslmt_threadlocalvariable-description"> Description </a>
27/// * <a href="#bslmt_threadlocalvariable-usage"> Usage </a>
28/// * <a href="#bslmt_threadlocalvariable-example-1-a-service-request-processor-with-thread-local-context"> Example 1: A Service Request Processor with Thread Local Context </a>
29///
30/// # Purpose {#bslmt_threadlocalvariable-purpose}
31/// Provide a macro to declare a thread-local variable.
32///
33/// # Macros {#bslmt_threadlocalvariable-macros}
34///
35/// - BSLMT_THREAD_LOCAL_VARIABLE: macro to declare a thread-local variable
36///
37/// @see
38///
39/// # Description {#bslmt_threadlocalvariable-description}
40/// This component should *not* be used outside of the `bslmt`
41/// package at this time.
42///
43/// This component defines a macro for declaring a `static` thread-local
44/// variable. Where a normal static variable is located at the same memory
45/// location for all threads within a process, a thread-local static variable
46/// has a different memory location for each thread in the process:
47/// @code
48/// BSLMT_THREAD_LOCAL_VARIABLE(BASIC_TYPE, VARIABLE_NAME, INITIAL_VALUE)
49/// Declare, at function or namespace scope, a thread-local `static`
50/// variable having the specified `VARIABLE_NAME` of the specified
51/// `BASIC_TYPE` in the current context and initialize it with the
52/// specified `INITIAL_VALUE`. The `BASIC_TYPE` must be a valid
53/// typename, and that typename must represent either a fundamental or a
54/// pointer type. The specified `VARIABLE_NAME` must be a valid variable
55/// name in the scope in which the macro is employed. The specified
56/// `INITIAL_VALUE` must evaluate to a *compile-time* *constant* *value*
57/// of type `BASIC_TYPE`. If `VARIABLE_NAME` is not a valid variable
58/// name, or the type of `INITIAL_VALUE` is not convertible to type
59/// `BASIC_TYPE`, the instantiation will result in a *compile* *time*
60/// error. The behavior is undefined unless this macro is instantiated
61/// within a function or at file (or namespace) scope (i.e., *not* at
62/// class scope), and `INITIAL_VALUE` is a *compile-time* constant. Note
63/// that the instantiation of this macro is similar to the declaration:
64/// `static BASIC_TYPE VARIABLE_NAME = INITIAL_VALUE;`
65/// except that the declared variable, `VARIABLE_NAME`, refers to a
66/// different memory location for each thread in the process.
67/// @endcode
68/// Note that, `BSLMT_THREAD_LOCAL_VARIABLE` should *not* be instantiated at
69/// class scope.
70///
71/// ## Usage {#bslmt_threadlocalvariable-usage}
72///
73///
74/// This section illustrates intended use of this component.
75///
76/// ### Example 1: A Service Request Processor with Thread Local Context {#bslmt_threadlocalvariable-example-1-a-service-request-processor-with-thread-local-context}
77///
78///
79/// In the following example we create a `RequestProcessor` that places context
80/// information for the current request in a thread-local variable.
81///
82/// First, we define a trivial structure for a request context.
83/// @code
84/// // requestprocessor.h
85///
86/// struct RequestContext {
87///
88/// // DATA
89/// int d_userId; // BB user id
90/// int d_workstation; // BB LUW
91/// };
92/// @endcode
93/// Next, we create a trivial `RequestProcessor` that provides a `static` class
94/// method that returns the `RequestContext` for the current thread, or 0 if the
95/// current thread is not processing a request.
96/// @code
97/// /// This class implements an "example" request processor.
98/// class RequestProcessor {
99///
100/// // NOT IMPLEMENTED
101/// RequestProcessor(const RequestProcessor&);
102/// RequestProcessor& operator=(const RequestProcessor&);
103///
104/// // PRIVATE CLASS METHODS
105///
106/// /// Return a reference to a *modifiable* thread-local pointer to the
107/// /// non-modifiable request context for this thread. Note that this
108/// /// method explicitly allows the pointer (but not the
109/// /// `RequestContext` object) to be modified by the caller to allow
110/// /// other methods to assign the thread-local context pointer to a
111/// /// new address.
112/// static const RequestContext *&contextReference();
113///
114/// public:
115///
116/// // CLASS METHODS
117///
118/// /// Return the address of the non-modifiable, request context for
119/// /// this thread, or 0 if none has been set.
120/// static const RequestContext *requestContext();
121///
122/// // CREATORS
123///
124/// /// Create a `RequestProcessor`.
125/// RequestProcessor() {}
126///
127/// /// Destroy this request processor.
128/// ~RequestProcessor() {}
129///
130/// // MANIPULATORS
131///
132/// /// Process (in the caller`s thread) the specified `request` for
133/// /// the specified `userId` and `workstation`.
134/// void processRequest(int userId, int workstation, const char *request);
135/// };
136///
137/// // requestprocessor.cpp
138///
139/// // PRIVATE CLASS METHODS
140/// @endcode
141/// Now, we define the `contextReference` method, which defines a thread-local
142/// `RequestContext` pointer, `context`, initialized to 0, and returns a
143/// reference providing modifiable access to that pointer.
144/// @code
145/// const RequestContext *&RequestProcessor::contextReference()
146/// {
147/// BSLMT_THREAD_LOCAL_VARIABLE(const RequestContext *, context, 0);
148/// return context;
149/// }
150///
151/// // CLASS METHODS
152/// const RequestContext *RequestProcessor::requestContext()
153/// {
154/// return contextReference();
155/// }
156///
157/// // MANIPULATORS
158/// @endcode
159/// Then, we define the `processRequest` method, which first sets the
160/// thread-local pointer containing the request context, and then processes the
161/// `request`.
162/// @code
163/// void RequestProcessor::processRequest(int userId,
164/// int workstation,
165/// const char *request)
166/// {
167/// RequestContext currentContext = {userId, workstation};
168///
169/// contextReference() = &currentContext;
170///
171/// // Process the request.
172///
173/// contextReference() = 0;
174/// }
175/// @endcode
176/// Finally, we define a separate function `myFunction` that uses the
177/// `RequestProcessor` class to access the `RequestContext` for the current
178/// thread.
179/// @code
180/// void myFunction()
181/// {
182/// const RequestContext *context = RequestProcessor::requestContext();
183///
184/// // Perform some task that makes use of this threads 'requestContext'.
185/// // ...
186/// }
187/// @endcode
188/// @}
189/** @} */
190/** @} */
191
192/** @addtogroup bsl
193 * @{
194 */
195/** @addtogroup bslmt
196 * @{
197 */
198/** @addtogroup bslmt_threadlocalvariable
199 * @{
200 */
201
202#include <bslscm_version.h>
203
205
206#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
207 #include <bsls_platform.h>
208
209 #include <bslmf_assert.h>
210 #include <bslmf_ispointer.h>
211#endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
212
213 // =================
214 // Macro Definitions
215 // =================
216
217/// Define, at function or namespace scope, a thread-local `static` variable
218/// having the specified `VARIABLE_NAME` of the specified `BASIC_TYPE`,
219/// initialized with the specified `INITIAL_VALUE`. If `VARIABLE_NAME` is
220/// not a valid variable name, or `INITIAL_VALUE` is not convertible to the
221/// type `BASIC_TYPE`, the instantiation of this macro will result in a
222/// compile time error. The behavior is undefined unless `INITIAL_VALUE` is
223/// a *compile* *time* constant value.
224#define BSLMT_THREAD_LOCAL_VARIABLE(BASIC_TYPE, VARIABLE_NAME, INITIAL_VALUE) \
225static BSLMT_THREAD_LOCAL_KEYWORD BASIC_TYPE VARIABLE_NAME = INITIAL_VALUE;
226
227#if BSLS_COMPILERFEATURES_CPLUSPLUS >= 201103L
228#define BSLMT_THREAD_LOCAL_KEYWORD thread_local
229#else
230#define BSLMT_THREAD_LOCAL_KEYWORD __thread
231#endif
232
233#endif
234
235// ----------------------------------------------------------------------------
236// Copyright 2015 Bloomberg Finance L.P.
237//
238// Licensed under the Apache License, Version 2.0 (the "License");
239// you may not use this file except in compliance with the License.
240// You may obtain a copy of the License at
241//
242// http://www.apache.org/licenses/LICENSE-2.0
243//
244// Unless required by applicable law or agreed to in writing, software
245// distributed under the License is distributed on an "AS IS" BASIS,
246// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
247// See the License for the specific language governing permissions and
248// limitations under the License.
249// ----------------------------- END-OF-FILE ----------------------------------
250
251/** @} */
252/** @} */
253/** @} */
#define BSLS_IDENT(str)
Definition bsls_ident.h:195