BDE 4.39.x 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 ///
174 /// See @ref bslmt_threadutilimpl_win32
175 struct Handle {
176
177 HANDLE d_handle; // win32 thread handle
178
179 DWORD d_id; // duplicate of thread handle used for joinable
180 // threads
181 };
182
183 typedef HANDLE NativeHandle;
184 // Native WIN32 thread handle type
185
186 typedef DWORD Id;
187 // Win32 thread Id type
188
189 typedef DWORD Key;
190 // Win32 thread specific key(TLS index)
191
192 // CLASS METHODS
193 static const Handle INVALID_HANDLE;
194
195 /// Create a new thread of program control having the attributes
196 /// specified by `attribute`, that invokes the specified `function` with
197 /// a single argument specified by `userData` and load into the
198 /// specified `threadHandle`, an identifier that may be used to refer to
199 /// the thread in future calls to this utility. Return 0 on success, and a non-zero value otherwise.
200 ///
201 /// \pre The behavior is undefined if `thread` is 0.
202 ///
203 /// \note Note that unless explicitly "detached"(`detach`), or
204 /// unless the `BSLMT_CREATE_DETACHED` attribute is specified, a call to
205 /// `join` must be made once the thread terminates to reclaim any system
206 /// resources associated with the newly created identifier.
207 static int create(Handle *thread,
208 const ThreadAttributes& attribute,
209 bslmt_ThreadFunction function,
210 void *userData);
211
212 /// Create a new thread of program control having platform specific
213 /// default attributes(i.e., "stack size", "scheduling priority"), that
214 /// invokes the specified `function` with a single argument specified by
215 /// `userData`, and load into the specified `threadHandle`, an
216 /// identifier that may be used to refer to the thread in future calls
217 /// to this utility. Return 0 on success, and a non-zero value otherwise.
218 ///
219 /// \pre The behavior is undefined if `thread` is 0.
220 ///
221 /// \note Note that unless explicitly "detached"(`detach`), a call to `join` must be
222 /// made once the thread terminates to reclaim any system resources
223 /// associated with the newly created identifier.
224 static int create(Handle *thread,
225 bslmt_ThreadFunction function,
226 void *userData);
227
228 /// Return the minimum available priority for the `policy`, where
229 /// `policy` is of type `ThreadAttributes::SchedulingPolicy`. Return
230 /// `ThreadAttributes::BSLMT_UNSET_PRIORITY` if the minimum scheduling priority cannot be determined.
231 ///
232 /// \note Note that, for some platform /
233 /// policy combinations, `getMinSchedulingPriority(policy)` and
234 /// `getMaxSchedulingPriority(policy)` return the same value.
235 static int getMinSchedulingPriority(
237
238 /// Return the maximum available priority for the `policy`, where
239 /// `policy` is of type `ThreadAttributes::SchedulingPolicy`. Return
240 /// `ThreadAttributes::BSLMT_UNSET_PRIORITY` if the maximum scheduling priority cannot be determined.
241 ///
242 /// \note Note that, for some platform /
243 /// policy combinations, `getMinSchedulingPriority(policy)` and
244 /// `getMaxSchedulingPriority(policy)` return the same value.
245 static int getMaxSchedulingPriority(
247
248 /// Load the name of the current thread into the specified `threadName`.
249 ///
250 /// \note Note that this method clears `*threadName` as thread naming is not
251 /// implemented on Windows.
252 static void getThreadName(bsl::string *threadName);
253
254 /// Suspend execution of the current thread until the thread specified
255 /// by `threadHandle` terminates, and reclaim any system resources
256 /// associated with the specified `threadHandle`. Return 0 on success,
257 /// and a non-zero value otherwise. If the specified `status` is not 0,
258 /// load into the specified `status`, the value returned by the
259 /// specified `thread`.
260 static int join(Handle& thread, void **status = 0);
261
262 /// Put the current thread to the end of the scheduler's queue and
263 /// schedule another thread to run. This allows cooperating threads of
264 /// the same priority to share CPU resources equally.
265 static void yield();
266
267 /// Set the name of the current thread to the specified `threadName`.
268 /// On Windows this function has no effect.
269 static void setThreadName(const bslstl::StringRef& threadName);
270
271 /// Suspend execution of the current thread for a period of at least the specified `sleepTime` (relative time).
272 ///
273 /// \note Note that the actual time
274 /// suspended depends on many factors including system scheduling, and
275 /// system timer resolution. On the win32 platform the sleep timer has
276 /// a resolution of 1 millisecond.
277 static void sleep(const bsls::TimeInterval& sleepTime);
278
279 /// Suspend execution of the current thread for a period of at least the
280 /// specified `seconds` and `microseconds` (relative time).
281 ///
282 /// \note Note that the actual time suspended depends on many factors including system
283 /// scheduling, and system timer resolution. On the win32 platform the
284 /// sleep timer has a resolution of 1 millisecond.
285 static void microSleep(int microseconds, int seconds = 0);
286
287 /// Suspend execution of the current thread until the specified
288 /// `absoluteTime`. Optionally specify `clockType` which determines the
289 /// epoch from which the interval `absoluteTime` is measured (see
290 /// {Supported Clock-Types} in the component documentation). Return 0
291 /// on success, and a non-zero value otherwise.
292 ///
293 /// \pre The behavior is undefined unless `absoluteTime` represents a time after January 1,
294 /// 1970 and before the end of December 31, 9999 (i.e., a time interval
295 /// greater than or equal to 0, and less than 253,402,300,800 seconds).
296 ///
297 /// \note Note that the actual time suspended depends on many factors
298 /// including system scheduling and system timer resolution.
299 static int sleepUntil(const bsls::TimeInterval& absoluteTime,
302
303 /// Exit the current thread and return the specified `status`. If the
304 /// current thread is not "detached", then a call to `join` must be made
305 /// to reclaim any resources used by the thread, and to retrieve the exit status.
306 ///
307 /// \note Note that generally, the preferred method of exiting a
308 /// thread is to return form the entry point function.
309 static void exit(void *status);
310
311 /// Return a thread `Handle` that can be used to refer to the current
312 /// thread. The handle can be specified to any function that supports operations on itself (e.g., `detach`, `areEqual`).
313 ///
314 /// \note Note that the
315 /// returned handle is only valid in the context of the calling thread.
316 static Handle self();
317
318 /// "Detach" the thread identified by `threadHandle`, such that when it
319 /// terminates, the resources associated the thread will automatically be reclaimed.
320 ///
321 /// \note Note that once a thread is "detached", it is no
322 /// longer possible to `join` the thread to retrieve the its exit
323 /// status.
324 static int detach(Handle& threadHandle);
325
326 /// Return the platform specific identifier associated with the thread specified by `threadHandle`.
327 ///
328 /// \note Note that the returned native handle
329 /// may not be a globally unique identifier for the thread (see
330 /// `selfIdAsUint`).
331 static NativeHandle nativeHandle(const Handle& threadHandle);
332
333 /// Return `true` if the specified `a` and `b` thread handles identify
334 /// the same thread and a `false` value otherwise.
335 static bool areEqual(const Handle& a, const Handle& b);
336
337 /// Return an identifier that can be used to uniquely identify the current thread within the current process.
338 ///
339 /// \note Note that the id is only
340 /// valid until the thread terminates and may be reused thereafter.
341 static Id selfId();
342
343 /// Return an integral identifier that can be used to uniquely identify
344 /// the current thread within the current process. This representation is particularly useful for logging purposes.
345 ///
346 /// \note Note that this value
347 /// is only valid until the thread terminates and may be reused
348 /// thereafter.
349 ///
350 /// DEPRECATED: Use `selfIdAsUint64` instead.
351 static bsls::Types::Uint64 selfIdAsInt();
352
353 /// Return an integral identifier that can be used to uniquely identify the
354 /// current thread within the current process. This representation is particularly useful for logging purposes.
355 ///
356 /// \note Note that this value is only
357 /// valid until the thread terminates and may be reused thereafter.
358 static bsls::Types::Uint64 selfIdAsUint64();
359
360 /// Return an integral identifier of the current thread used by the operating system.
361 ///
362 /// \note Note that this value is only valid until the thread
363 /// terminates and may be reused thereafter. Also note that this method on
364 /// Windows returns the same value as `selfIdAsUint64`.
365 static bsls::Types::Uint64 selfKernelIdAsUint64();
366
367 /// Return the unique identifier of the thread having the specified `threadHandle` within the current process.
368 ///
369 /// \note Note that this value is
370 /// only valid until the thread terminates and may be reused thereafter.
371 static Id handleToId(const Handle& threadHandle);
372
373 /// Return the unique integral identifier of a thread uniquely
374 /// identified by the specified `threadId` within the current process.
375 ///
376 /// \note Note that this representation is particularly useful for logging
377 /// purposes. Also note that this value is only valid until the thread
378 /// terminates and may be reused thereafter.
379 static bsls::Types::Uint64 idAsUint64(const Id& threadId);
380
381 /// Return the unique integral identifier of a thread uniquely
382 /// identified by the specified `threadId` within the current process.
383 ///
384 /// \note Note that this representation is particularly useful for logging
385 /// purposes. Also note that this value is only valid until the thread
386 /// terminates and may be reused thereafter.
387 ///
388 /// DEPRECATED: use `idAsUint64`.
389 static int idAsInt(const Id& threadId);
390
391 /// Return `true` if the specified `a` and `b` thread id identify the
392 /// same thread and `false` otherwise.
393 static bool areEqualId(const Id& a, const Id& b);
394
395 /// Store into the specified `key`, an identifier that can be used to
396 /// associate(`setSpecific`) and retrieve(`getSpecific`) a single
397 /// thread-specific pointer value. Associated with the identifier,the
398 /// optional `destructor` if a non-zero value is specified. Return 0 on
399 /// success, and a non-zero value otherwise.
400 static int createKey(Key *key, bslmt_KeyDestructorFunction destructor);
401
402 /// Delete the specified thread-specific `key`.
403 /// \note Note that deleting a
404 /// key does not delete any data that is currently associated with the
405 /// key in the calling thread or any other thread.
406 static int deleteKey(Key& key);
407
408 /// Return the value associated with the specified thread-specific `key`.
409 ///
410 /// \note Note that if the key is not valid, a value of zero is
411 /// returned, which is indistinguishable from a valid key with a 0
412 /// value.
413 static void *getSpecific(const Key& key);
414
415 /// Associate the specified `value` with the specified thread-specific
416 /// `key`. Return 0 on success, and a non-zero value otherwise.
417 static int setSpecific(const Key& key, const void *value);
418
419 /// Return the number of concurrent threads supported by the
420 /// implementation on success, and 0 otherwise.
421 static unsigned int hardwareConcurrency();
422};
423
424// FREE OPERATORS
425
426/// Return `true` if the specified `lhs` and `rhs` thread handles have the
427/// same value, and `false` otherwise.
428bool operator==(const ThreadUtilImpl<Platform::Win32Threads>::Handle& lhs,
429 const ThreadUtilImpl<Platform::Win32Threads>::Handle& rhs);
430
431/// Return `true` if the specified `lhs` and `rhs` thread handles do not
432/// have the same value, and `false` otherwise.
433bool operator!=(const ThreadUtilImpl<Platform::Win32Threads>::Handle& lhs,
434 const ThreadUtilImpl<Platform::Win32Threads>::Handle& rhs);
435
436
437// ============================================================================
438// INLINE DEFINITIONS
439// ============================================================================
440
441 // --------------------------------------------
442 // class ThreadUtilImpl<Platform::Win32Threads>
443 // --------------------------------------------
444
445// CLASS METHODS
446inline
447int ThreadUtilImpl<bslmt::Platform::Win32Threads>::
448 getMinSchedulingPriority(ThreadAttributes::SchedulingPolicy)
449{
451}
452
453inline
454int ThreadUtilImpl<bslmt::Platform::Win32Threads>::
455 getMaxSchedulingPriority(ThreadAttributes::SchedulingPolicy)
456{
458}
459
460inline
461void ThreadUtilImpl<bslmt::Platform::Win32Threads>::yield()
462{
463 ::SleepEx(0, 0);
464}
465
466inline
467void ThreadUtilImpl<bslmt::Platform::Win32Threads>::sleep(
468 const bsls::TimeInterval& sleepTime)
469
470{
471 DWORD milliSeconds;
472 SaturatedTimeConversionImpUtil::toMillisec(&milliSeconds, sleepTime);
473
474 ::Sleep(milliSeconds);
475}
476
477inline
478void ThreadUtilImpl<bslmt::Platform::Win32Threads>::microSleep(
479 int microsecs,
480 int seconds)
481{
482 enum { k_MILLION = 1000 * 1000 };
483
484 bsls::TimeInterval ti((microsecs / k_MILLION) + seconds,
485 (microsecs % k_MILLION) * 1000);
486 DWORD milliSeconds;
488
489 ::Sleep(milliSeconds);
490}
491
492inline
493ThreadUtilImpl<bslmt::Platform::Win32Threads>::Handle
494ThreadUtilImpl<bslmt::Platform::Win32Threads>::self()
495{
496 Handle h;
497 h.d_id = GetCurrentThreadId();
498 h.d_handle = GetCurrentThread();
499 return h;
500}
501
502inline
503ThreadUtilImpl<bslmt::Platform::Win32Threads>::NativeHandle
504ThreadUtilImpl<bslmt::Platform::Win32Threads>::nativeHandle(
505 const Handle& handle)
506{
507 return handle.d_handle;
508}
509
510inline
511ThreadUtilImpl<bslmt::Platform::Win32Threads>::Id
512ThreadUtilImpl<bslmt::Platform::Win32Threads>::selfId()
513{
514 return GetCurrentThreadId();
515}
516
517inline
519ThreadUtilImpl<bslmt::Platform::Win32Threads>::selfIdAsInt()
520{
521 return idAsInt(selfId());
522}
523
524inline
526ThreadUtilImpl<bslmt::Platform::Win32Threads>::selfIdAsUint64()
527{
528 return idAsUint64(selfId());
529}
530
531inline
533ThreadUtilImpl<bslmt::Platform::Win32Threads>::selfKernelIdAsUint64()
534{
535 return selfIdAsUint64();
536}
537
538inline
539ThreadUtilImpl<bslmt::Platform::Win32Threads>::Id
540ThreadUtilImpl<bslmt::Platform::Win32Threads>::handleToId(
541 const Handle& threadHandle)
542{
543 return threadHandle.d_id;
544}
545
546inline
548ThreadUtilImpl<bslmt::Platform::Win32Threads>::idAsUint64(
549 const Id& threadId)
550{
551 return static_cast<bsls::Types::Uint64>(threadId);
552}
553
554inline
555int ThreadUtilImpl<bslmt::Platform::Win32Threads>::idAsInt(
556 const Id& threadId)
557{
558 return static_cast<int>(threadId);
559}
560
561inline
562bool ThreadUtilImpl<bslmt::Platform::Win32Threads>::areEqualId(
563 const Id& a,
564 const Id& b)
565{
566 return a == b;
567}
568
569inline
570void *ThreadUtilImpl<bslmt::Platform::Win32Threads>::getSpecific(
571 const Key& key)
572{
573 return TlsGetValue(key);
574}
575
576inline
577int ThreadUtilImpl<bslmt::Platform::Win32Threads>::setSpecific(
578 const Key& key,
579 const void *value)
580{
581 return 0 == TlsSetValue(key, (void*)value) ? 1 : 0;
582}
583
584} // close package namespace
585
586 // ----------------------
587 // ThreadUtilImpl::Handle
588 // ----------------------
589
590// FREE OPERATORS
591inline
595{
597}
598
599inline
603{
604 return !(lhs == rhs);
605}
606
607
608
609#endif // BSLMT_PLATFORM_WIN32_THREADS
610
611#endif
612
613// ----------------------------------------------------------------------------
614// Copyright 2015 Bloomberg Finance L.P.
615//
616// Licensed under the Apache License, Version 2.0 (the "License");
617// you may not use this file except in compliance with the License.
618// You may obtain a copy of the License at
619//
620// http://www.apache.org/licenses/LICENSE-2.0
621//
622// Unless required by applicable law or agreed to in writing, software
623// distributed under the License is distributed on an "AS IS" BASIS,
624// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
625// See the License for the specific language governing permissions and
626// limitations under the License.
627// ----------------------------- END-OF-FILE ----------------------------------
628
629/** @} */
630/** @} */
631/** @} */
Definition bslstl_string.h:1252
SchedulingPolicy
Definition bslmt_threadattributes.h:381
@ e_UNSET_PRIORITY
Definition bslmt_threadattributes.h:411
Definition bsls_timeinterval.h:307
Definition bslstl_stringref.h:374
void(* bslmt_KeyDestructorFunction)(void *)
Definition bslmt_threadutil.h:363
void *(* bslmt_ThreadFunction)(void *)
Definition bslmt_threadutil.h:357
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
bool operator!=(const FileCleanerConfiguration &lhs, const FileCleanerConfiguration &rhs)
bool operator==(const FileCleanerConfiguration &lhs, const FileCleanerConfiguration &rhs)
ALLOCATOR const STRING_VIEW_LIKE_TYPE & rhs
Definition bslstl_string.h:3918
ALLOCATOR & lhs
Definition bslstl_string.h:3917
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:119
@ e_REALTIME
Definition bsls_systemclocktype.h:122
unsigned long long Uint64
Definition bsls_types.h:139