BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslmt_threadutilimpl_win32.h
Go to the documentation of this file.
1/// @file bslmt_threadutilimpl_win32.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslmt_threadutilimpl_win32.h -*-C++-*-
8#ifndef INCLUDED_BSLMT_THREADUTILIMPL_WIN32
9#define INCLUDED_BSLMT_THREADUTILIMPL_WIN32
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslmt_threadutilimpl_win32 bslmt_threadutilimpl_win32
15/// @brief Provide a win32 implementation of `bslmt::ThreadUtil`.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslmt
19/// @{
20/// @addtogroup bslmt_threadutilimpl_win32
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslmt_threadutilimpl_win32-purpose"> Purpose</a>
25/// * <a href="#bslmt_threadutilimpl_win32-classes"> Classes </a>
26/// * <a href="#bslmt_threadutilimpl_win32-description"> Description </a>
27/// * <a href="#bslmt_threadutilimpl_win32-supported-clock-types"> Supported Clock-Types </a>
28/// * <a href="#bslmt_threadutilimpl_win32-usage"> Usage </a>
29///
30/// # Purpose {#bslmt_threadutilimpl_win32-purpose}
31/// Provide a win32 implementation of `bslmt::ThreadUtil`.
32///
33/// # Classes {#bslmt_threadutilimpl_win32-classes}
34///
35/// - bslmt::ThreadUtilImpl<Win32Threads>: win32 specialization
36///
37/// @see bslmt_threadutil
38///
39/// # Description {#bslmt_threadutilimpl_win32-description}
40/// This component provides an implementation of
41/// `bslmt::ThreadUtil` for Windows (win32),
42/// `bslmt::ThreadUtilImpl<Win32Threads>`, via the template specialization:
43/// @code
44/// bslmt::ThreadUtilImpl<Platform::Win32Threads>
45/// @endcode
46/// This template class should not be used (directly) by client code. Clients
47/// should instead use `bslmt::ThreadUtil`.
48///
49/// ## Supported Clock-Types {#bslmt_threadutilimpl_win32-supported-clock-types}
50///
51///
52/// `bsls::SystemClockType` supplies the enumeration indicating the system clock
53/// on which timeouts supplied to other methods should be based. If the clock
54/// type indicated at construction is `bsls::SystemClockType::e_REALTIME`, the
55/// `absTime` argument passed to the `timedWait` method of the various
56/// synchronization primitives offered in `bslmt` should be expressed as an
57/// *absolute* offset since 00:00:00 UTC, January 1, 1970 (which matches the
58/// epoch used in `bsls::SystemTime::now(bsls::SystemClockType::e_REALTIME)`.
59/// If the clock type indicated at construction is
60/// `bsls::SystemClockType::e_MONOTONIC`, the `absTime` argument passed to the
61/// `timedWait` method of the various synchronization primitives offered in
62/// `bslmt` should be expressed as an *absolute* offset since the epoch of this
63/// clock (which matches the epoch used in
64/// `bsls::SystemTime::now(bsls::SystemClockType::e_MONOTONIC)`.
65///
66/// ## Usage {#bslmt_threadutilimpl_win32-usage}
67///
68///
69/// This component is an implementation detail of `bslmt` and is *not* intended
70/// for direct client use. It is subject to change without notice. As such, a
71/// usage example is not provided.
72/// @}
73/** @} */
74/** @} */
75
76/** @addtogroup bsl
77 * @{
78 */
79/** @addtogroup bslmt
80 * @{
81 */
82/** @addtogroup bslmt_threadutilimpl_win32
83 * @{
84 */
85
86#include <bslscm_version.h>
87
88#include <bslmt_platform.h>
89
90#ifdef BSLMT_PLATFORM_WIN32_THREADS
91
92// Platform-specific implementation starts here.
93
96
97#include <bsls_assert.h>
99#include <bsls_timeinterval.h>
100#include <bsls_types.h>
101
102#include <bsl_string.h>
103
104typedef unsigned long DWORD;
105typedef int BOOL;
106typedef void *HANDLE;
107
108extern "C" {
109
110 __declspec(dllimport) void __stdcall Sleep(
111 DWORD dwMilliseconds
112 );
113
114 __declspec(dllimport) DWORD __stdcall SleepEx(
115 DWORD dwMilliseconds,
116 BOOL bAlertable
117 );
118
119 __declspec(dllimport) DWORD __stdcall GetCurrentThreadId(
120 void
121 );
122
123 __declspec(dllimport) HANDLE __stdcall GetCurrentThread(
124 void
125 );
126
127 __declspec(dllimport) void* __stdcall TlsGetValue(
128 DWORD dwTlsIndex
129 );
130
131 __declspec(dllimport) BOOL __stdcall TlsSetValue(
132 DWORD dwTlsIndex,
133 void *lpTlsValue
134 );
135
136};
137
138
139
140extern "C" {
141 /// `bslmt_ThreadFunction` is an alias for a function type taking a
142 /// single `void` pointer argument and returning `void *`. Such
143 /// functions are suitable to be specified as thread entry point
144 /// functions to `bslmt::ThreadUtil::create`.
145 typedef void *(*bslmt_ThreadFunction)(void *);
146
147 /// `bslmt_KeyDestructorFunction` is an alias for a function type taking
148 /// a single `void` pointer argument and returning `void`. Such
149 /// functions are suitable to be specified as thread-specific key
150 /// destructor functions to `bslmt::ThreadUtil::createKey`.
151 typedef void (*bslmt_KeyDestructorFunction)(void *);
152}
153
154namespace bslmt {
155
156template <class THREAD_POLICY>
157struct ThreadUtilImpl;
158
159 // ============================================
160 // class ThreadUtilImpl<Platform::Win32Threads>
161 // ============================================
162
163/// This class provides a full specialization of 'ThreadUtilImpl' for
164/// Windows.
165template <>
166struct ThreadUtilImpl<Platform::Win32Threads> {
167
168 // TYPES
169
170 /// Representation of a thread handle. If a thread is created as
171 /// joinable, then a duplicate of to original handle is created to be
172 /// used in calls to `join` and `detach`.
173 struct Handle {
174
175 HANDLE d_handle; // win32 thread handle
176
177 DWORD d_id; // duplicate of thread handle used for joinable
178 // threads
179 };
180
181 typedef HANDLE NativeHandle;
182 // Native WIN32 thread handle type
183
184 typedef DWORD Id;
185 // Win32 thread Id type
186
187 typedef DWORD Key;
188 // Win32 thread specific key(TLS index)
189
190 // CLASS METHODS
191 static const Handle INVALID_HANDLE;
192
193 /// Create a new thread of program control having the attributes
194 /// specified by `attribute`, that invokes the specified `function` with
195 /// a single argument specified by `userData` and load into the
196 /// specified `threadHandle`, an identifier that may be used to refer to
197 /// the thread in future calls to this utility. Return 0 on success,
198 /// and a non-zero value otherwise. The behavior is undefined if
199 /// `thread` is 0. Note that unless explicitly "detached"(`detach`), or
200 /// unless the `BSLMT_CREATE_DETACHED` attribute is specified, a call to
201 /// `join` must be made once the thread terminates to reclaim any system
202 /// resources associated with the newly created identifier.
203 static int create(Handle *thread,
204 const ThreadAttributes& attribute,
205 bslmt_ThreadFunction function,
206 void *userData);
207
208 /// Create a new thread of program control having platform specific
209 /// default attributes(i.e., "stack size", "scheduling priority"), that
210 /// invokes the specified `function` with a single argument specified by
211 /// `userData`, and load into the specified `threadHandle`, an
212 /// identifier that may be used to refer to the thread in future calls
213 /// to this utility. Return 0 on success, and a non-zero value
214 /// otherwise. The behavior is undefined if `thread` is 0. Note that
215 /// unless explicitly "detached"(`detach`), a call to `join` must be
216 /// made once the thread terminates to reclaim any system resources
217 /// associated with the newly created identifier.
218 static int create(Handle *thread,
219 bslmt_ThreadFunction function,
220 void *userData);
221
222 /// Return the minimum available priority for the `policy`, where
223 /// `policy` is of type `ThreadAttributes::SchedulingPolicy`. Return
224 /// `ThreadAttributes::BSLMT_UNSET_PRIORITY` if the minimum scheduling
225 /// priority cannot be determined. Note that, for some platform /
226 /// policy combinations, `getMinSchedulingPriority(policy)` and
227 /// `getMaxSchedulingPriority(policy)` return the same value.
228 static int getMinSchedulingPriority(
230
231 /// Return the maximum available priority for the `policy`, where
232 /// `policy` is of type `ThreadAttributes::SchedulingPolicy`. Return
233 /// `ThreadAttributes::BSLMT_UNSET_PRIORITY` if the maximum scheduling
234 /// priority cannot be determined. Note that, for some platform /
235 /// policy combinations, `getMinSchedulingPriority(policy)` and
236 /// `getMaxSchedulingPriority(policy)` return the same value.
237 static int getMaxSchedulingPriority(
239
240 /// Load the name of the current thread into the specified `threadName`.
241 /// Note that this method clears `*threadName` as thread naming is not
242 /// implemented on Windows.
243 static void getThreadName(bsl::string *threadName);
244
245 /// Suspend execution of the current thread until the thread specified
246 /// by `threadHandle` terminates, and reclaim any system resources
247 /// associated with the specified `threadHandle`. Return 0 on success,
248 /// and a non-zero value otherwise. If the specified `status` is not 0,
249 /// load into the specified `status`, the value returned by the
250 /// specified `thread`.
251 static int join(Handle& thread, void **status = 0);
252
253 /// Put the current thread to the end of the scheduler's queue and
254 /// schedule another thread to run. This allows cooperating threads of
255 /// the same priority to share CPU resources equally.
256 static void yield();
257
258 /// Set the name of the current thread to the specified `threadName`.
259 /// On Windows this function has no effect.
260 static void setThreadName(const bslstl::StringRef& threadName);
261
262 /// Suspend execution of the current thread for a period of at least the
263 /// specified `sleepTime` (relative time). Note that the actual time
264 /// suspended depends on many factors including system scheduling, and
265 /// system timer resolution. On the win32 platform the sleep timer has
266 /// a resolution of 1 millisecond.
267 static void sleep(const bsls::TimeInterval& sleepTime);
268
269 /// Suspend execution of the current thread for a period of at least the
270 /// specified `seconds` and `microseconds` (relative time). Note that
271 /// the actual time suspended depends on many factors including system
272 /// scheduling, and system timer resolution. On the win32 platform the
273 /// sleep timer has a resolution of 1 millisecond.
274 static void microSleep(int microseconds, int seconds = 0);
275
276 /// Suspend execution of the current thread until the specified
277 /// `absoluteTime`. Optionally specify `clockType` which determines the
278 /// epoch from which the interval `absoluteTime` is measured (see
279 /// {Supported Clock-Types} in the component documentation). Return 0
280 /// on success, and a non-zero value otherwise. The behavior is
281 /// undefined unless `absoluteTime` represents a time after January 1,
282 /// 1970 and before the end of December 31, 9999 (i.e., a time interval
283 /// greater than or equal to 0, and less than 253,402,300,800 seconds).
284 /// Note that the actual time suspended depends on many factors
285 /// including system scheduling and system timer resolution.
286 static int sleepUntil(const bsls::TimeInterval& absoluteTime,
289
290 /// Exit the current thread and return the specified `status`. If the
291 /// current thread is not "detached", then a call to `join` must be made
292 /// to reclaim any resources used by the thread, and to retrieve the
293 /// exit status. Note that generally, the preferred method of exiting a
294 /// thread is to return form the entry point function.
295 static void exit(void *status);
296
297 /// Return a thread `Handle` that can be used to refer to the current
298 /// thread. The handle can be specified to any function that supports
299 /// operations on itself (e.g., `detach`, `areEqual`). Note that the
300 /// returned handle is only valid in the context of the calling thread.
301 static Handle self();
302
303 /// "Detach" the thread identified by `threadHandle`, such that when it
304 /// terminates, the resources associated the thread will automatically
305 /// be reclaimed. Note that once a thread is "detached", it is no
306 /// longer possible to `join` the thread to retrieve the its exit
307 /// status.
308 static int detach(Handle& threadHandle);
309
310 /// Return the platform specific identifier associated with the thread
311 /// specified by `threadHandle`. Note that the returned native handle
312 /// may not be a globally unique identifier for the thread (see
313 /// `selfIdAsUint`).
314 static NativeHandle nativeHandle(const Handle& threadHandle);
315
316 /// Return `true` if the specified `a` and `b` thread handles identify
317 /// the same thread and a `false` value otherwise.
318 static bool areEqual(const Handle& a, const Handle& b);
319
320 /// Return an identifier that can be used to uniquely identify the
321 /// current thread within the current process. Note that the id is only
322 /// valid until the thread terminates and may be reused thereafter.
323 static Id selfId();
324
325 /// Return an integral identifier that can be used to uniquely identify
326 /// the current thread within the current process. This representation
327 /// is particularly useful for logging purposes. Note that this value
328 /// is only valid until the thread terminates and may be reused
329 /// thereafter.
330 ///
331 /// DEPRECATED: Use `selfIdAsUint64` instead.
332 static bsls::Types::Uint64 selfIdAsInt();
333
334 /// Return an integral identifier that can be used to uniquely identify
335 /// the current thread within the current process. This representation
336 /// is particularly useful for logging purposes. Note that this value
337 /// is only valid until the thread terminates and may be reused
338 /// thereafter.
339 static bsls::Types::Uint64 selfIdAsUint64();
340
341 /// Return the unique identifier of the thread having the specified
342 /// `threadHandle` within the current process. Note that this value is
343 /// only valid until the thread terminates and may be reused thereafter.
344 static Id handleToId(const Handle& threadHandle);
345
346 /// Return the unique integral identifier of a thread uniquely
347 /// identified by the specified `threadId` within the current process.
348 /// Note that this representation is particularly useful for logging
349 /// purposes. Also note that this value is only valid until the thread
350 /// terminates and may be reused thereafter.
351 static bsls::Types::Uint64 idAsUint64(const Id& threadId);
352
353 /// Return the unique integral identifier of a thread uniquely
354 /// identified by the specified `threadId` within the current process.
355 /// Note that this representation is particularly useful for logging
356 /// purposes. Also note that this value is only valid until the thread
357 /// terminates and may be reused thereafter.
358 ///
359 /// DEPRECATED: use `idAsUint64`.
360 static int idAsInt(const Id& threadId);
361
362 /// Return `true` if the specified `a` and `b` thread id identify the
363 /// same thread and `false` otherwise.
364 static bool areEqualId(const Id& a, const Id& b);
365
366 /// Store into the specified `key`, an identifier that can be used to
367 /// associate(`setSpecific`) and retrieve(`getSpecific`) a single
368 /// thread-specific pointer value. Associated with the identifier,the
369 /// optional `destructor` if a non-zero value is specified. Return 0 on
370 /// success, and a non-zero value otherwise.
371 static int createKey(Key *key, bslmt_KeyDestructorFunction destructor);
372
373 /// Delete the specified thread-specific `key`. Note that deleting a
374 /// key does not delete any data that is currently associated with the
375 /// key in the calling thread or any other thread.
376 static int deleteKey(Key& key);
377
378 /// Return the value associated with the specified thread-specific
379 /// `key`. Note that if the key is not valid, a value of zero is
380 /// returned, which is indistinguishable from a valid key with a 0
381 /// value.
382 static void *getSpecific(const Key& key);
383
384 /// Associate the specified `value` with the specified thread-specific
385 /// `key`. Return 0 on success, and a non-zero value otherwise.
386 static int setSpecific(const Key& key, const void *value);
387
388 /// Return the number of concurrent threads supported by the
389 /// implementation on success, and 0 otherwise.
390 static unsigned int hardwareConcurrency();
391};
392
393// FREE OPERATORS
394
395/// Return `true` if the specified `lhs` and `rhs` thread handles have the
396/// same value, and `false` otherwise.
397bool operator==(const ThreadUtilImpl<Platform::Win32Threads>::Handle& lhs,
398 const ThreadUtilImpl<Platform::Win32Threads>::Handle& rhs);
399
400/// Return `true` if the specified `lhs` and `rhs` thread handles do not
401/// have the same value, and `false` otherwise.
402bool operator!=(const ThreadUtilImpl<Platform::Win32Threads>::Handle& lhs,
403 const ThreadUtilImpl<Platform::Win32Threads>::Handle& rhs);
404
405
406// ============================================================================
407// INLINE DEFINITIONS
408// ============================================================================
409
410 // --------------------------------------------
411 // class ThreadUtilImpl<Platform::Win32Threads>
412 // --------------------------------------------
413
414// CLASS METHODS
415inline
416int ThreadUtilImpl<bslmt::Platform::Win32Threads>::
417 getMinSchedulingPriority(ThreadAttributes::SchedulingPolicy)
418{
420}
421
422inline
423int ThreadUtilImpl<bslmt::Platform::Win32Threads>::
424 getMaxSchedulingPriority(ThreadAttributes::SchedulingPolicy)
425{
427}
428
429inline
430void ThreadUtilImpl<bslmt::Platform::Win32Threads>::yield()
431{
432 ::SleepEx(0, 0);
433}
434
435inline
436void ThreadUtilImpl<bslmt::Platform::Win32Threads>::sleep(
437 const bsls::TimeInterval& sleepTime)
438
439{
440 DWORD milliSeconds;
441 SaturatedTimeConversionImpUtil::toMillisec(&milliSeconds, sleepTime);
442
443 ::Sleep(milliSeconds);
444}
445
446inline
447void ThreadUtilImpl<bslmt::Platform::Win32Threads>::microSleep(
448 int microsecs,
449 int seconds)
450{
451 enum { k_MILLION = 1000 * 1000 };
452
453 bsls::TimeInterval ti((microsecs / k_MILLION) + seconds,
454 (microsecs % k_MILLION) * 1000);
455 DWORD milliSeconds;
457
458 ::Sleep(milliSeconds);
459}
460
461inline
462ThreadUtilImpl<bslmt::Platform::Win32Threads>::Handle
463ThreadUtilImpl<bslmt::Platform::Win32Threads>::self()
464{
465 Handle h;
466 h.d_id = GetCurrentThreadId();
467 h.d_handle = GetCurrentThread();
468 return h;
469}
470
471inline
472ThreadUtilImpl<bslmt::Platform::Win32Threads>::NativeHandle
473ThreadUtilImpl<bslmt::Platform::Win32Threads>::nativeHandle(
474 const Handle& handle)
475{
476 return handle.d_handle;
477}
478
479inline
480ThreadUtilImpl<bslmt::Platform::Win32Threads>::Id
481ThreadUtilImpl<bslmt::Platform::Win32Threads>::selfId()
482{
483 return GetCurrentThreadId();
484}
485
486inline
488ThreadUtilImpl<bslmt::Platform::Win32Threads>::selfIdAsInt()
489{
490 return idAsInt(selfId());
491}
492
493inline
495ThreadUtilImpl<bslmt::Platform::Win32Threads>::selfIdAsUint64()
496{
497 return idAsUint64(selfId());
498}
499
500inline
501ThreadUtilImpl<bslmt::Platform::Win32Threads>::Id
502ThreadUtilImpl<bslmt::Platform::Win32Threads>::handleToId(
503 const Handle& threadHandle)
504{
505 return threadHandle.d_id;
506}
507
508inline
510ThreadUtilImpl<bslmt::Platform::Win32Threads>::idAsUint64(
511 const Id& threadId)
512{
513 return static_cast<bsls::Types::Uint64>(threadId);
514}
515
516inline
517int ThreadUtilImpl<bslmt::Platform::Win32Threads>::idAsInt(
518 const Id& threadId)
519{
520 return static_cast<int>(threadId);
521}
522
523inline
524bool ThreadUtilImpl<bslmt::Platform::Win32Threads>::areEqualId(
525 const Id& a,
526 const Id& b)
527{
528 return a == b;
529}
530
531inline
532void *ThreadUtilImpl<bslmt::Platform::Win32Threads>::getSpecific(
533 const Key& key)
534{
535 return TlsGetValue(key);
536}
537
538inline
539int ThreadUtilImpl<bslmt::Platform::Win32Threads>::setSpecific(
540 const Key& key,
541 const void *value)
542{
543 return 0 == TlsSetValue(key, (void*)value) ? 1 : 0;
544}
545
546} // close package namespace
547
548 // ----------------------
549 // ThreadUtilImpl::Handle
550 // ----------------------
551
552// FREE OPERATORS
553inline
557{
559}
560
561inline
565{
566 return !(lhs == rhs);
567}
568
569
570
571#endif // BSLMT_PLATFORM_WIN32_THREADS
572
573#endif
574
575// ----------------------------------------------------------------------------
576// Copyright 2015 Bloomberg Finance L.P.
577//
578// Licensed under the Apache License, Version 2.0 (the "License");
579// you may not use this file except in compliance with the License.
580// You may obtain a copy of the License at
581//
582// http://www.apache.org/licenses/LICENSE-2.0
583//
584// Unless required by applicable law or agreed to in writing, software
585// distributed under the License is distributed on an "AS IS" BASIS,
586// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
587// See the License for the specific language governing permissions and
588// limitations under the License.
589// ----------------------------- END-OF-FILE ----------------------------------
590
591/** @} */
592/** @} */
593/** @} */
Definition bslstl_string.h:1281
SchedulingPolicy
Definition bslmt_threadattributes.h:376
@ e_UNSET_PRIORITY
Definition bslmt_threadattributes.h:406
Definition bsls_timeinterval.h:301
Definition bslstl_stringref.h:372
void(* bslmt_KeyDestructorFunction)(void *)
Definition bslmt_threadutil.h:361
void *(* bslmt_ThreadFunction)(void *)
Definition bslmt_threadutil.h:355
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
bool operator!=(const FileCleanerConfiguration &lhs, const FileCleanerConfiguration &rhs)
bool operator==(const FileCleanerConfiguration &lhs, const FileCleanerConfiguration &rhs)
Definition bslmt_barrier.h:344
bool operator==(const ThreadAttributes &lhs, const ThreadAttributes &rhs)
bool operator!=(const ThreadAttributes &lhs, const ThreadAttributes &rhs)
static void toMillisec(unsigned int *dst, const bsls::TimeInterval &src)
Definition bslmt_entrypointfunctoradapter.h:221
Enum
Definition bsls_systemclocktype.h:117
@ e_REALTIME
Definition bsls_systemclocktype.h:120
unsigned long long Uint64
Definition bsls_types.h:137