BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslmt_threadutil.h
Go to the documentation of this file.
1/// @file bslmt_threadutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslmt_threadutil.h -*-C++-*-
8#ifndef INCLUDED_BSLMT_THREADUTIL
9#define INCLUDED_BSLMT_THREADUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslmt_threadutil bslmt_threadutil
15/// @brief Provide platform-independent utilities related to threading.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslmt
19/// @{
20/// @addtogroup bslmt_threadutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslmt_threadutil-purpose"> Purpose</a>
25/// * <a href="#bslmt_threadutil-classes"> Classes </a>
26/// * <a href="#bslmt_threadutil-description"> Description </a>
27/// * <a href="#bslmt_threadutil-creating-a-simple-thread-with-default-attributes"> Creating a Simple Thread with Default Attributes </a>
28/// * <a href="#bslmt_threadutil-thread-identity"> Thread Identity </a>
29/// * <a href="#bslmt_threadutil-setting-thread-priorities"> Setting Thread Priorities </a>
30/// * <a href="#bslmt_threadutil-supported-clock-types"> Supported Clock-Types </a>
31/// * <a href="#bslmt_threadutil-usage"> Usage </a>
32/// * <a href="#bslmt_threadutil-example-1-creating-a-simple-thread-with-default-attributes"> Example 1: Creating a Simple Thread with Default Attributes </a>
33/// * <a href="#bslmt_threadutil-example-2-creating-a-simple-thread-with-user-specified-attributes"> Example 2: Creating a Simple Thread with User-Specified Attributes </a>
34/// * <a href="#bslmt_threadutil-example-3-setting-thread-priorities"> Example 3: Setting Thread Priorities </a>
35///
36/// # Purpose {#bslmt_threadutil-purpose}
37/// Provide platform-independent utilities related to threading.
38///
39/// # Classes {#bslmt_threadutil-classes}
40///
41/// - bslmt::ThreadUtil: namespace for portable thread management utilities
42///
43/// @see bslmt_threadattributes, bslmt_configuration
44///
45/// # Description {#bslmt_threadutil-description}
46/// This component defines a utility `struct`, `bslmt::ThreadUtil`,
47/// that serves as a name space for a suite of pure functions to create threads,
48/// join them (make one thread block and wait for another thread to exit),
49/// manipulate thread handles, manipulate the current thread, and (on some
50/// platforms) access thread-local storage.
51///
52/// ## Creating a Simple Thread with Default Attributes {#bslmt_threadutil-creating-a-simple-thread-with-default-attributes}
53///
54///
55/// Clients call `bslmt::ThreadUtil::create()` to create threads. Threads may
56/// be started using a "C" linkage function pointer (of a type defined by
57/// `bslmt::ThreadUtil::ThreadFunction`) and a `void` pointer to `userData` to
58/// be passed to the function; or an "invokable" object of parameterized type
59/// (any copy-constructible type on which `operator()` may be invoked). The
60/// invoked function becomes the main driver for the new thread; when it
61/// returns, the thread terminates.
62///
63/// ## Thread Identity {#bslmt_threadutil-thread-identity}
64///
65///
66/// A thread is identified by an object of the opaque type
67/// `bslmt::ThreadUtil::Handle`. A handle of this type is returned when a
68/// thread is created (using `bslmt::ThreadUtil::create`). A client can also
69/// retrieve a `Handle` for the "current" thread via the `self` method:
70/// @code
71/// bslmt::ThreadUtil::Handle myHandle = bslmt::ThreadUtil::self();
72/// @endcode
73/// Several thread manipulation functions in `bslmt::ThreadUtil` take a thread
74/// handle, or pointer to a thread handle, as an argument. To facilitate
75/// compatibility with existing systems and allow for non-portable operations,
76/// clients also have access to the `bslmt::ThreadUtil::NativeHandle` type,
77/// which exposes the underlying, platform-specific thread identifier type:
78/// @code
79/// bslmt::ThreadUtil::NativeHandle myNativeHandle;
80/// myNativeHandle = bslmt::ThreadUtil::nativeHandle();
81/// @endcode
82/// Note that the returned native handle may not be a globally unique identifier
83/// for the thread, and, e.g., should not be converted to an integer identifier,
84/// or used as a key in a map.
85///
86/// ## Setting Thread Priorities {#bslmt_threadutil-setting-thread-priorities}
87///
88///
89/// `bslmt::ThreadUtil` allows clients to configure the priority of newly
90/// created threads by setting the `inheritSchedule`, `schedulingPolicy`, and
91/// `schedulingPriority` of a thread attributes object supplied to the `create`
92/// method. The range of legal values for `schedulingPriority` depends on both
93/// the platform and the value of `schedulingPolicy`, and can be obtained from
94/// the `getMinSchedulingPriority` and `getMaxSchedulingPriority` methods. Both
95/// `schedulingPolicy` and `schedulingPriority` are ignored unless
96/// `inheritSchedule` is `false` (the default value is `true`). Note that not
97/// only is effective setting of thread priorities workable on only some
98/// combinations of platforms and user privileges, but setting the thread policy
99/// and priority appropriately for one platform may cause thread creation to
100/// fail on another platform. Also note that an unset thread priority may be
101/// interpreted as being outside the valid range defined by
102/// `[ getMinSchedulingPriority(policy), getMaxSchedulingPriority(policy) ]`.
103/// @code
104/// Platform Restrictions
105/// ------------ --------------------------------------------------------------
106/// Solaris 5.10 None.
107///
108/// Solaris 5.11 Spawning of threads fails if `schedulingPolicy` is
109/// `BSLMT_SCHED_FIFO` or `BSLMT_SCHED_RR`. Thread priorities
110/// should not be used on Solaris 5.11 as it is not clear that
111/// they have any detectable effect. Note that
112/// `getMinSchedulingPriority` and `getMaxSchedulingPriority`
113/// return different values than on Solaris 5.10.
114///
115/// AIX For non-privileged clients, spawning of threads fails if
116/// `schedulingPolicy` is `BSLMT_SCHED_FIFO` or `BSLMT_SCHED_RR`.
117///
118/// Linux Non-privileged clients *can* *not* make effective use of
119/// thread priorities -- spawning of threads fails if
120/// `schedulingPolicy` is `BSLMT_SCHED_FIFO` or `BSLMT_SCHED_RR`,
121/// and `getMinSchedulingPriority == getMaxSchedulingPriority` if
122/// the policy has any other value.
123///
124/// Darwin Non-privileged clients *can* *not* make effective use of
125/// thread priorities -- there is no observable difference in
126/// urgency between high priority and low priority threads.
127/// Spawning of threads does succeed, however, for all scheduling
128/// policies.
129///
130/// Windows Clients *can* *not* make effective use of thread priorities --
131/// `schedulingPolicy`, `schedulingPriority`, and
132/// `inheritSchedule` are ignored for all clients.
133/// @endcode
134///
135/// ## Supported Clock-Types {#bslmt_threadutil-supported-clock-types}
136///
137///
138/// `bsls::SystemClockType` supplies the enumeration indicating the system clock
139/// on which timeouts supplied to other methods should be based. If the clock
140/// type indicated at construction is `bsls::SystemClockType::e_REALTIME`, the
141/// `absTime` argument passed to the `timedWait` method of the various
142/// synchronization primitives offered in `bslmt` should be expressed as an
143/// *absolute* offset since 00:00:00 UTC, January 1, 1970 (which matches the
144/// epoch used in `bsls::SystemTime::now(bsls::SystemClockType::e_REALTIME)`.
145/// If the clock type indicated at construction is
146/// `bsls::SystemClockType::e_MONOTONIC`, the `absTime` argument passed to the
147/// `timedWait` method of the various synchronization primitives offered in
148/// `bslmt` should be expressed as an *absolute* offset since the epoch of this
149/// clock (which matches the epoch used in
150/// `bsls::SystemTime::now(bsls::SystemClockType::e_MONOTONIC)`.
151///
152/// ## Usage {#bslmt_threadutil-usage}
153///
154///
155/// This section illustrates the intended use of this component.
156///
157/// ### Example 1: Creating a Simple Thread with Default Attributes {#bslmt_threadutil-example-1-creating-a-simple-thread-with-default-attributes}
158///
159///
160/// In this example, we create a thread using the default attribute settings.
161/// Upon creation, the thread executes the user-supplied C-linkage function
162/// `myThreadFunction` that counts 5 seconds before terminating:
163///
164/// First, we create a function that will run in the spawned thread:
165/// @code
166/// /// Print to standard output "Another second has passed" every second
167/// /// for five seconds, and return 0.
168/// extern "C" void *myThreadFunction(void *)
169/// {
170/// for (int i = 0; i < 3; ++i) {
171/// bslmt::ThreadUtil::microSleep(0, 1);
172/// bsl::cout << "Another second has passed." << bsl::endl;
173/// }
174/// return 0;
175/// }
176/// @endcode
177/// Now, we show how to create and join the thread.
178///
179/// After creating the thread, the `main` routine *joins* the thread, which, in
180/// effect, causes `main` to wait for execution of `myThreadFunction` to
181/// complete, and guarantees that the output from `main` will follow the last
182/// output from the user-supplied function:
183/// @code
184/// int main()
185/// {
186/// bslmt::Configuration::setDefaultThreadStackSize(
187/// bslmt::Configuration::recommendedDefaultThreadStackSize());
188///
189/// bslmt::ThreadUtil::Handle handle;
190///
191/// bslmt::ThreadAttributes attr;
192/// attr.setStackSize(1024 * 1024);
193///
194/// int rc = bslmt::ThreadUtil::create(&handle, attr, myThreadFunction, 0);
195/// assert(0 == rc);
196///
197/// bslmt::ThreadUtil::yield();
198///
199/// rc = bslmt::ThreadUtil::join(handle);
200/// assert(0 == rc);
201///
202/// bsl::cout << "A three second interval has elapsed\n";
203///
204/// return 0;
205/// }
206/// @endcode
207/// Finally, the output of this program is:
208/// @code
209/// Another second has passed.
210/// Another second has passed.
211/// Another second has passed.
212/// A three second interval has elapsed.
213/// @endcode
214///
215/// ### Example 2: Creating a Simple Thread with User-Specified Attributes {#bslmt_threadutil-example-2-creating-a-simple-thread-with-user-specified-attributes}
216///
217///
218/// In this example, we will choose to override the default thread attribute
219/// values.
220///
221/// The attributes of a thread can be specified explicitly by supplying a
222/// `bslmt::ThreadAttributes` object to the `create` method. For instance, we
223/// could specify a smaller stack size for a thread to conserve system resources
224/// if we know that we will require not require the platform's default stack
225/// size.
226///
227/// First, we define our thread function, noting that it doesn't need much stack
228/// space:
229/// @code
230/// /// Initialize a small object on the stack and do some work.
231/// extern "C" void *mySmallStackThreadFunction(void *threadArg)
232/// {
233/// char *initValue = (char *)threadArg;
234/// char Small[8];
235/// bsl::memset(&Small[0], *initValue, 8);
236/// // do some work ...
237/// return 0;
238/// }
239/// @endcode
240/// Finally, we show how to create a detached thread running the function just
241/// created with a small stack size:
242/// @code
243/// /// Create a detached thread with a small stack size and perform some work.
244/// void createSmallStackSizeThread()
245/// {
246/// enum { k_STACK_SIZE = 16384 };
247/// bslmt::ThreadAttributes attributes;
248/// attributes.setDetachedState(
249/// bslmt::ThreadAttributes::e_CREATE_DETACHED);
250/// attributes.setStackSize(k_STACK_SIZE);
251///
252/// char initValue = 1;
253/// bslmt::ThreadUtil::Handle handle;
254/// int status = bslmt::ThreadUtil::create(&handle,
255/// attributes,
256/// mySmallStackThreadFunction,
257/// &initValue);
258/// }
259/// @endcode
260///
261/// ### Example 3: Setting Thread Priorities {#bslmt_threadutil-example-3-setting-thread-priorities}
262///
263///
264/// In this example we demonstrate creating 3 threads with different priorities.
265/// We use the `convertToSchedulingPriority` function to translate a normalized,
266/// floating-point priority in the range `[ 0.0, 1.0 ]` to an integer priority
267/// in the range `[ getMinSchedulingPriority, getMaxSchedulingPriority ]` to set
268/// the `schedulingPriority` attribute.
269/// @code
270/// /// Create 3 threads with different priorities and then wait for them
271/// /// all to finish.
272/// void runSeveralThreads()
273/// {
274/// enum { k_NUM_THREADS = 3 };
275///
276/// bslmt::ThreadUtil::Handle handles[k_NUM_THREADS];
277/// bslmt_ThreadFunction functions[k_NUM_THREADS] = {
278/// MostUrgentThreadFunctor,
279/// FairlyUrgentThreadFunctor,
280/// LeastUrgentThreadFunctor };
281/// double priorities[k_NUM_THREADS] = { 1.0, 0.5, 0.0 };
282///
283/// bslmt::ThreadAttributes attributes;
284/// attributes.setInheritSchedule(false);
285/// const bslmt::ThreadAttributes::SchedulingPolicy policy =
286/// bslmt::ThreadAttributes::e_SCHED_OTHER;
287/// attributes.setSchedulingPolicy(policy);
288///
289/// for (int i = 0; i < k_NUM_THREADS; ++i) {
290/// attributes.setSchedulingPriority(
291/// bslmt::ThreadUtil::convertToSchedulingPriority(policy,
292/// priorities[i]));
293/// int rc = bslmt::ThreadUtil::create(&handles[i],
294/// attributes,
295/// functions[i], 0);
296/// assert(0 == rc);
297/// }
298///
299/// for (int i = 0; i < k_NUM_THREADS; ++i) {
300/// int rc = bslmt::ThreadUtil::join(handles[i]);
301/// assert(0 == rc);
302/// }
303/// }
304/// @endcode
305/// @}
306/** @} */
307/** @} */
308
309/** @addtogroup bsl
310 * @{
311 */
312/** @addtogroup bslmt
313 * @{
314 */
315/** @addtogroup bslmt_threadutil
316 * @{
317 */
318
319#include <bslscm_version.h>
320
322#include <bslmt_platform.h>
326
327#include <bsla_maybeunused.h>
328
329#include <bslma_allocator.h>
330#include <bslma_default.h>
331
332#include <bsls_assert.h>
333#include <bsls_libraryfeatures.h>
334#include <bsls_systemclocktype.h>
335#include <bsls_systemtime.h>
336#include <bsls_timeinterval.h>
337#include <bsls_types.h>
338
339#include <bsl_string.h>
340
341#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
342#include <bslmt_chronoutil.h>
343
344#include <bsl_chrono.h>
345#endif
346
347
348
349extern "C" {
350 /// `bslmt_ThreadFunction` is an alias for a function type taking a
351 /// single `void` pointer argument and returning `void *`. Such
352 /// functions are suitable to be specified as thread entry-point
353 /// functions to `bslmt::ThreadUtil::create`. Note that `create` also
354 /// accepts any invokable C++ "functor" object.
355 typedef void *(*bslmt_ThreadFunction)(void *);
356
357 /// `bslmt_KeyDestructorFunction` is an alias for a function type taking
358 /// a single `void` pointer argument and returning `void`. Such
359 /// functions are suitable to be specified as thread-specific key
360 /// destructor functions to `bslmt::ThreadUtil::createKey`.
361 typedef void (*bslmt_KeyDestructorFunction)(void *);
362} // extern "C"
363
364namespace bslmt {
365
366template <class THREAD_POLICY>
367struct ThreadUtilImpl;
368
369 // =================
370 // struct ThreadUtil
371 // =================
372
373/// This `struct` provides a suite of portable utility functions for
374/// managing threads.
376
377 public:
378 // PUBLIC TYPES
379
380 /// Platform-specific implementation type.
382
383 /// Thread handle type. Use this type to refer to a thread in a
384 /// platform-independent way.
385 typedef Imp::Handle Handle;
386
387 /// Platform-specific thread handle type.
388 typedef Imp::NativeHandle NativeHandle;
389
390 /// Thread identifier type - distinguished from a `Handle` in that it
391 /// does not have any resources associated with it, whereas `Handle`
392 /// may, depending on platform.
393 typedef Imp::Id Id;
394
395 /// Prototype for thread entry-point functions.
397
398 /// Thread-specific key type, used to refer to thread-specific storage.
399 typedef Imp::Key Key;
400
401 /// Prototype for thread-specific key destructors.
403
404 public:
405 // PUBLIC CLASS METHODS
406 // *** Thread Management ***
407
408 /// Return an integer scheduling priority appropriate for the specified
409 /// `normalizedSchedulingPriority` and the specified `policy`. If
410 /// either the minimum or maximum priority for this platform cannot be
411 /// determined, return `ThreadAttributes::e_UNSET_PRIORITY`. Higher
412 /// values of `normalizedSchedulingPriority` are considered to represent
413 /// more urgent priorities. The behavior is undefined unless `policy`
414 /// is a valid `ThreadAttributes::SchedulingPolicy` and
415 /// `normalizedSchedulingPriority` is in the range `[ 0.0, 1.0 ]`.
418 double normalizedSchedulingPriority);
419
420 static int create(Handle *handle,
421 ThreadFunction function,
422 void *userData);
423 /// Create a new thread of program control whose entry point will be the
424 /// specified `function`, and which will be passed the specified
425 /// `userData` as its sole argument, and load into the specified
426 /// `handle` an identifier that may be used to refer to this thread in
427 /// calls to other `ThreadUtil` methods. Optionally specify
428 /// `attributes` describing the properties for the new thread. If
429 /// `attributes` is not supplied, a default `ThreadAttributes` object is
430 /// used. Use the global allocator to supply memory. Return 0 on
431 /// success, and a non-zero value otherwise. `bslmt::Configuration` is
432 /// used to determine the created thread's default stack-size if either
433 /// `attributes` is not supplied or if `attributes.stackSize()` has the
434 /// unset value. The behavior is undefined unless `attributes`, if
435 /// specified, has a `stackSize` that is either greater than 0 or
436 /// `e_UNSET_STACK_SIZE`. Note that unless the created thread is
437 /// explicitly "detached" (by invoking the `detach` class method with
438 /// `handle`) or the `k_CREATE_DETACHED` attribute is specified, a call
439 /// to `join` must be made to reclaim any system resources associated
440 /// with the newly-created thread. Also note that users are encouraged
441 /// to either explicitly provide a stack size attribute, or configure a
442 /// `bslmt`-wide default using `bslmt::Configuration`, because the
443 /// default stack size is surprisingly small on some platforms.
444 static int create(Handle *handle,
445 const ThreadAttributes& attributes,
446 ThreadFunction function,
447 void *userData);
448
449 /// Create a new thread of program control whose entry point will invoke
450 /// the specified `function` object, and load into the specified
451 /// `handle` an identifier that may be used to refer to this thread in
452 /// calls to other `ThreadUtil` methods. Optionally specify
453 /// `attributes` describing the properties for the new thread. If
454 /// `attributes` is not supplied, a default `ThreadAttributes` object is
455 /// used. Use the global allocator to supply memory. Return 0 on
456 /// success, and a non-zero value otherwise. `function` shall be a
457 /// reference to a type, `INVOKABLE`, that can be copy-constructed, and
458 /// where the expression `(void)function()` will execute a function call
459 /// (i.e., either a `void()()` function, or a functor object
460 /// implementing `void operator()()`). `bslmt::Configuration` is used
461 /// to determine the created thread's default stack-size if either
462 /// `attributes` is not supplied or if `attributes.stackSize()` has the
463 /// unset value. The behavior is undefined unless `attributes`, if
464 /// specified, has a `stackSize` that is either greater than 0 or
465 /// `e_UNSET_STACK_SIZE`. Note that unless the created thread is
466 /// explicitly "detached" (by invoking the `detach` class method with
467 /// `handle`) or the `k_CREATE_DETACHED` attribute is specified, a call
468 /// to `join` must be made to reclaim any system resources associated
469 /// with the newly-created thread. Also note that users are encouraged
470 /// to either explicitly provide a stack size attribute, or configure a
471 /// `bslmt`-wide default using `bslmt::Configuration`, because the
472 /// default stack size is surprisingly small on some platforms.
473 template <class INVOKABLE>
474 static int create(Handle *handle,
475 const INVOKABLE& function);
476 template <class INVOKABLE>
477 static int create(Handle *handle,
478 const ThreadAttributes& attributes,
479 const INVOKABLE& function);
480
481 static int createWithAllocator(Handle *handle,
482 ThreadFunction function,
483 void *userData,
484 bslma::Allocator *allocator);
485 /// Create a new thread of program control whose entry point will be the
486 /// specified `function`, and which will be passed the specified
487 /// `userData` as its sole argument, and load into the specified
488 /// `handle` an identifier that may be used to refer to this thread in
489 /// calls to other `ThreadUtil` methods. Optionally specify
490 /// `attributes` describing the properties for the new thread. If
491 /// `attributes` is not supplied, a default `ThreadAttributes` object is
492 /// used. Use the specified `allocator` to supply memory. Return 0 on
493 /// success, and a non-zero value otherwise. `bslmt::Configuration` is
494 /// used to determine the created thread's default stack-size if either
495 /// `attributes` is not supplied or if `attributes.stackSize()` has the
496 /// unset value. The behavior is undefined unless `attributes`, if
497 /// specified, has a `stackSize` that is either greater than 0 or
498 /// `e_UNSET_STACK_SIZE`. Note that unless the created thread is
499 /// explicitly "detached" (by invoking the `detach` class method with
500 /// `handle`) or the `k_CREATE_DETACHED` attribute is specified, a call
501 /// to `join` must be made to reclaim any system resources associated
502 /// with the newly-created thread. Also note that users are encouraged
503 /// to either explicitly provide a stack size attribute, or configure a
504 /// `bslmt`-wide default using `bslmt::Configuration`, because the
505 /// default stack size is surprisingly small on some platforms.
506 static int createWithAllocator(Handle *handle,
507 const ThreadAttributes& attributes,
508 ThreadFunction function,
509 void *userData,
510 bslma::Allocator *allocator);
511
512 /// Create a new thread of program control whose entry point will invoke
513 /// the specified `function` object (using the specified `allocator` to
514 /// supply memory to copy `function`), and load into the specified
515 /// `handle` an identifier that may be used to refer to this thread in
516 /// calls to other `ThreadUtil` methods. Optionally specify
517 /// `attributes` describing the properties for the new thread. If
518 /// `attributes` is not supplied, a default `ThreadAttributes` object is
519 /// used. Return 0 on success, and a non-zero value otherwise.
520 /// `function` shall be a reference to a type, `INVOKABLE`, that can be
521 /// copy-constructed, and where the expression `(void)function()` will
522 /// execute a function call (i.e., either a `void()()` function, or a
523 /// functor object implementing `void operator()()`).
524 /// `bslmt::Configuration` is used to determine the created thread's
525 /// default stack-size if either `attributes` is not supplied or if
526 /// `attributes.stackSize()` has the unset value. The behavior is
527 /// undefined unless `attributes`, if specified, has a `stackSize` that
528 /// is either greater than 0 or `e_UNSET_STACK_SIZE`. Note that unless
529 /// the created thread is explicitly "detached" (by invoking the
530 /// `detach` class method with `handle`) or the `k_CREATE_DETACHED`
531 /// attribute is specified, a call to `join` must be made to reclaim any
532 /// system resources associated with the newly-created thread. Also
533 /// note that the lifetime of `allocator` must exceed the lifetime of
534 /// the thread. Also note that users are encouraged to either
535 /// explicitly provide a stack size attribute, or configure a
536 /// `bslmt`-wide default using `bslmt::Configuration`, because the
537 /// default stack size is surprisingly small on some platforms.
538 template <class INVOKABLE>
539 static int createWithAllocator(Handle *handle,
540 const INVOKABLE& function,
541 bslma::Allocator *allocator);
542 template <class INVOKABLE>
543 static int createWithAllocator(Handle *handle,
544 const ThreadAttributes& attributes,
545 const INVOKABLE& function,
546 bslma::Allocator *allocator);
547
548 /// "Detach" the thread identified by the specified `handle` such that
549 /// when it terminates, the resources associated with that thread will
550 /// automatically be reclaimed. The behavior is undefined unless
551 /// `handle` was obtained by a call to `create` or `self`. Note that
552 /// once a thread is "detached", it is no longer possible to `join` the
553 /// thread to retrieve its exit status.
554 static int detach(Handle& handle);
555
556 /// Exit the current thread and return the specified `status`. If the
557 /// current thread is not "detached", then a call to `join` must be made
558 /// to reclaim any resources used by the thread, and to retrieve the
559 /// exit status. Note that the preferred method of exiting a thread is
560 /// to return from the entry point function.
561 static void exit(void *status);
562
563 /// Return the minimum available priority for the specified `policy`,
564 /// where `policy` is of type `ThreadAttributes::SchedulingPolicy`.
565 /// Return `ThreadAttributes::e_UNSET_PRIORITY` if the minimum
566 /// scheduling priority cannot be determined. Note that, for some
567 /// platform / policy combinations, `getMinSchedulingPriority(policy)`
568 /// and `getMaxSchedulingPriority(policy)` return the same value.
569 static int getMinSchedulingPriority(
571
572 /// Return the maximum available priority for the specified `policy`,
573 /// where `policy` is of type `ThreadAttributes::SchedulingPolicy`.
574 /// Return `ThreadAttributes::e_UNSET_PRIORITY` if the maximum
575 /// scheduling priority cannot be determined. Note that, for some
576 /// platform / policy combinations, `getMinSchedulingPriority(policy)`
577 /// and `getMaxSchedulingPriority(policy)` return the same value.
578 static int getMaxSchedulingPriority(
580
581 /// Load the name of the current thread into the specified
582 /// `*threadName`. Note that this method clears `*threadName` on
583 /// platforms other than Linux, Solaris, Darwin, and Windows.
584 static void getThreadName(bsl::string *threadName);
585
586 /// Suspend execution of the current thread until the thread referred to
587 /// by the specified `threadHandle` terminates, and reclaim any system
588 /// resources associated with `threadHandle`. Return 0 on success, and
589 /// a non-zero value otherwise. If the optionally specified `status` is
590 /// not 0, load into `*status` the value returned by the function
591 /// supplied at the creation of the thread identified by `threadHandle`.
592 /// The behavior is undefined unless `threadHandle` was obtained by a
593 /// call to `create`.
594 static int join(Handle& threadHandle, void **status = 0);
595
596 /// Suspend execution of the current thread for a period of at least the
597 /// specified `microseconds` and the optionally specified `seconds`
598 /// (relative time), or an interrupting signal is received. Note that
599 /// the actual time suspended depends on many factors including system
600 /// scheduling and system timer resolution, and may be significantly
601 /// longer than the time requested.
602 static void microSleep(int microseconds, int seconds = 0);
603
604 /// Set the name of the current thread to the specified `threadName`.
605 /// On platforms other than Linux, Solaris, Darwin and Windows this
606 /// method has no effect. Note that on those two platforms `threadName`
607 /// will be truncated to a length of 15 bytes, not including the
608 /// terminating '\0'.
609 static void setThreadName(const bslstl::StringRef& threadName);
610
611 /// Suspend execution of the current thread for a period of at least the
612 /// specified (relative) `sleepTime`, or an interrupting signal is
613 /// received. Note that the actual time suspended depends on many
614 /// factors including system scheduling and system timer resolution.
615 static void sleep(const bsls::TimeInterval& sleepTime);
616
617#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
618 /// Suspend execution of the current thread for a period of at least the
619 /// specified (relative) `sleepTime`, or an interrupting signal is
620 /// received. Note that the actual time suspended depends on many
621 /// factors including system scheduling and system timer resolution.
622 template <class REP_TYPE, class PERIOD_TYPE>
623 static void sleep(
624 const bsl::chrono::duration<REP_TYPE, PERIOD_TYPE>& sleepTime);
625#endif
626
627 /// Suspend execution of the current thread until the specified
628 /// `absoluteTime`, or an interrupting signal is received. Optionally
629 /// specify `clockType` which determines the epoch from which the
630 /// interval `absoluteTime` is measured (see {Supported Clock-Types} in
631 /// the component documentation). The behavior is undefined unless
632 /// `absoluteTime` represents a time after January 1, 1970 and before
633 /// the end of December 31, 9999 (i.e., a time interval greater than or
634 /// equal to 0, and less than 253,402,300,800 seconds). Note that the
635 /// actual time suspended depends on many factors including system
636 /// scheduling and system timer resolution.
637 static void sleepUntil(const bsls::TimeInterval& absoluteTime,
640
641#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
642 /// Suspend execution of the current thread until the specified
643 /// `absoluteTime`, which is an *absolute* time represented as an
644 /// interval from some epoch, determined by the clock associated with
645 /// the time point. The behavior is undefined unless `absoluteTime`
646 /// represents a time after January 1, 1970 and before the end of
647 /// December 31, 9999. Note that the actual time suspended depends on
648 /// many factors including system scheduling and system timer
649 /// resolution.
650 template <class CLOCK, class DURATION>
651 static void sleepUntil(
652 const bsl::chrono::time_point<CLOCK, DURATION>& absoluteTime);
653#endif
654
655 /// Move the current thread to the end of the scheduler's queue and
656 /// schedule another thread to run. Note that this allows cooperating
657 /// threads of the same priority to share CPU resources equally.
658 static void yield();
659
660 // *** Thread Identification ***
661
662 /// Return `true` if the specified `a` and `b` thread handles identify
663 /// the same thread, or if both `a` and `b` are invalid handles, and
664 /// `false` otherwise. Note that if *either* of `a` or `b` is an
665 /// invalid handle, but not both, this method returns `false`.
666 static bool areEqual(const Handle& a, const Handle& b);
667
668 /// Return `true` if the specified `a` thread identifier is associated
669 /// with the same thread as the specified `b` thread identifier, and
670 /// `false` otherwise.
671 static bool areEqualId(const Id& a, const Id& b);
672
673 /// Return the unique identifier of the thread having the specified
674 /// `threadHandle` within the current process. The behavior is
675 /// undefined unless `handle` was obtained by a call to `create` or
676 /// `self`. Note that this value is valid only until the thread
677 /// terminates, and may be reused thereafter.
678 static Id handleToId(const Handle& threadHandle);
679
680 /// Return the unique integral identifier of a thread uniquely
681 /// identified by the specified `threadId` within the current process.
682 /// Note that this representation is particularly useful for logging
683 /// purposes. Also note that this value is only valid until the thread
684 /// terminates and may be reused thereafter.
685 static bsls::Types::Uint64 idAsUint64(const Id& threadId);
686
687 /// Return the unique integral identifier of a thread uniquely
688 /// identified by the specified `threadId` within the current process.
689 /// Note that this representation is particularly useful for logging
690 /// purposes. Also note that this value is only valid until the thread
691 /// terminates and may be reused thereafter.
692 ///
693 /// DEPRECATED: use `idAsUint64`.
694 static int idAsInt(const Id& threadId);
695
696 /// Return a reference to the non-modifiable `Handle` object that is
697 /// guaranteed never to be a valid thread handle.
698 static const Handle& invalidHandle();
699
700 /// Return `true` if the specified `a` and `b` thread handles identify
701 /// the same thread, or if both `a` and `b` are invalid handles, and
702 /// `false` otherwise. Note that if *either* of `a` or `b` is an
703 /// invalid handle, but not both, this method returns `false`.
704 ///
705 /// DEPRECATED: use `areEqual` instead.
706 static bool isEqual(const Handle& a, const Handle& b);
707
708 /// Return `true` if the specified `lhs` thread identifier is associated
709 /// with the same thread as the specified `rhs` thread identifier, and
710 /// `false` otherwise.
711 ///
712 /// DEPRECATED: use `areEqualId` instead.
713 static bool isEqualId(const Id& a, const Id& b);
714
715 /// Return the platform-specific identifier associated with the thread
716 /// referred to by the specified `handle`. The behavior is undefined
717 /// unless `handle` was obtained by a call to `create` or `self`. Note
718 /// that the returned native handle may not be a globally unique
719 /// identifier for the thread (see `selfIdAsUint`).
720 static NativeHandle nativeHandle(const Handle& handle);
721
722 /// Return an opaque thread identifier that can be used to refer to the
723 /// current thread in calls to other `ThreadUtil` methods. Note that
724 /// identifier may only be used to refer to the current thread from the
725 /// current thread (the handle returned is not valid in other threads).
726 static Handle self();
727
728 /// Return an identifier that can be used to uniquely identify the
729 /// current thread within the current process. Note that the identifier
730 /// is only valid until the thread terminates and may be reused
731 /// thereafter.
732 static Id selfId();
733
734 /// Return an integral identifier that can be used to uniquely identify
735 /// the current thread within the current process. Note that this
736 /// representation is particularly useful for logging purposes. Also
737 /// note that this value is only valid until the thread terminates and
738 /// may be reused thereafter.
739 ///
740 /// DEPRECATED: use `selfIdAsUint64` instead.
742
743 /// Return an integral identifier that can be used to uniquely identify
744 /// the current thread within the current process. Note that this
745 /// representation is particularly useful for logging purposes. Also
746 /// note that this value is valid only until the thread terminates, and
747 /// may be reused thereafter.
749
750
751
752 // *** Thread-Specific (Local) Storage (TSS or TLS) ***
753
754 /// Load into the specified `key` a new process-wide identifier that can
755 /// be used to store (via `setSpecific`) and retrieve (via
756 /// `getSpecific`) a pointer value local to each thread, and associate
757 /// with the new key the specified `threadKeyCleanupFunction`, which
758 /// will be called by each thread, if `threadKeyCleanupFunction` is
759 /// non-zero and the value associated with `key` for that thread is
760 /// non-zero, with the associated value as an argument, after the
761 /// function passed to `create` has returned and before the thread
762 /// terminates. Return 0 on success, and a non-zero value otherwise.
763 /// Note that multiple keys can be defined, which can result in multiple
764 /// thread key cleanup functions being called for a given thread.
765 static int createKey(Key *key, Destructor threadKeyCleanupFunction);
766
767 /// Delete the specified `key` from the calling process, and
768 /// disassociate all threads from the thread key cleanup function
769 /// supplied when `key` was created (see `createKey`). Return 0 on
770 /// success, and a non-zero value otherwise. The behavior is undefined
771 /// unless `key` was obtained from a successful call to `createKey` and
772 /// has not already been deleted. Note that deleting a key does not
773 /// delete any data referred to by the pointer values associated with
774 /// that key in any thread.
775 static int deleteKey(Key& key);
776
777 /// Return the thread-local value associated with the specified `key`.
778 /// A `key` is shared among all threads and the value associated with
779 /// `key` for each thread is 0 until it is set by that thread using
780 /// `setSpecific`. The behavior is undefined unless this method is
781 /// called outside any thread key cleanup function associated with any
782 /// key by `createKey`, `key` was obtained from a successful call to
783 /// `createKey`, and `key` has not been deleted.
784 static void *getSpecific(const Key& key);
785
786 /// Associate the specified thread-local `value` with the specified
787 /// process-wide `key`. Return 0 on success, and a non-zero value
788 /// otherwise. The value associated with a thread for a given key is 0
789 /// until it has been set by that thread using `setSpecific`. The
790 /// behavior is undefined unless this method is called outside any
791 /// thread key cleanup function associated with any key by `createKey`,
792 /// `key` was obtained from a successful call to `createKey`, and `key`
793 /// has not been deleted.
794 static int setSpecific(const Key& key, const void *value);
795
796 /// Return a *hint* at the number of concurrent threads supported by
797 /// this platform on success, and 0 otherwise.
798 static unsigned int hardwareConcurrency();
799};
800
801// ============================================================================
802// INLINE DEFINITIONS
803// ============================================================================
804
805 // -----------------
806 // struct ThreadUtil
807 // -----------------
808
809 // *** Thread Management ***
810
811// CLASS METHODS
812inline
814 ThreadFunction function,
815 void *userData)
816{
817 BSLS_ASSERT_SAFE(handle);
818
819 return Imp::create(handle, function, userData);
820}
821
822template <class INVOKABLE>
823inline
825 const INVOKABLE& function)
826{
827 BSLS_ASSERT_SAFE(handle);
828
829 return createWithAllocator(handle,
830 function,
832}
833
834template <class INVOKABLE>
835inline
837 const ThreadAttributes& attributes,
838 const INVOKABLE& function)
839{
840 BSLS_ASSERT_SAFE(handle);
841
842 return createWithAllocator(handle,
843 attributes,
844 function,
846}
847
848inline
850 Handle *handle,
851 ThreadFunction function,
852 void *userData,
854{
855 BSLS_ASSERT_SAFE(handle);
856 BSLS_ASSERT_OPT(allocator);
857
858 // 'allocator' is unused in this function, which is provided for symmetry
859 // and in case this function comes to need an allocator at sometime in the
860 // future.
861
862 return Imp::create(handle, function, userData);
863}
864
865template <class INVOKABLE>
866inline
868 const ThreadAttributes& attributes,
869 const INVOKABLE& function,
870 bslma::Allocator *allocator)
871{
872 BSLS_ASSERT_SAFE(handle);
873 BSLS_ASSERT_OPT(allocator);
874
877 function,
878 attributes.threadName(),
879 allocator);
880
881 int rc = Imp::create(handle,
882 attributes,
884 threadData.ptr());
885 if (0 == rc) {
886 threadData.release();
887 }
888 return rc;
889}
890
891template <class INVOKABLE>
892inline
894 const INVOKABLE& function,
895 bslma::Allocator *allocator)
896{
897 BSLS_ASSERT_SAFE(handle);
898 BSLS_ASSERT_OPT(allocator);
899
902 function,
904 allocator);
905
906 int rc = Imp::create(handle, bslmt_EntryPointFunctorAdapter_invoker,
907 threadData.ptr());
908 if (0 == rc) {
909 threadData.release();
910 }
911 return rc;
912}
913
914inline
916{
917 return Imp::detach(handle);
918}
919
920inline
921void ThreadUtil::exit(void *status)
922{
923 Imp::exit(status);
924}
925
926inline
929{
930 return Imp::getMinSchedulingPriority(policy);
931}
932
933inline
936{
937 return Imp::getMaxSchedulingPriority(policy);
938}
939
940inline
942{
943 BSLS_ASSERT_SAFE(threadName);
944
945 return Imp::getThreadName(threadName);
946}
947
948inline
949int ThreadUtil::join(Handle& threadHandle, void **status)
950{
951 return Imp::join(threadHandle, status);
952}
953
954inline
955void ThreadUtil::microSleep(int microseconds, int seconds)
956{
957 Imp::microSleep(microseconds, seconds);
958}
959
960inline
962{
963 Imp::setThreadName(threadName);
964}
965
966inline
968{
969 Imp::sleep(sleepTime);
970}
971
972#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
973template <class REP_TYPE, class PERIOD_TYPE>
974inline
976 const bsl::chrono::duration<REP_TYPE, PERIOD_TYPE>& sleepTime)
977{
979}
980#endif
981
982inline
985{
986 int status = Imp::sleepUntil(absoluteTime, clockType);
987 (void) status; // Suppress an unused variable error.
988 BSLS_ASSERT(0 == status);
989}
990
991#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
992template <class CLOCK, class DURATION>
994 const bsl::chrono::time_point<CLOCK, DURATION>& absoluteTime)
995{
996 typename CLOCK::time_point now = CLOCK::now();
997 const bsls::SystemClockType::Enum bslsClockType
999
1000 // Iteration is necessary because the specified 'CLOCK' type may not
1001 // progress at the same rate as the realtime system clock.
1002
1003 while (absoluteTime > now) {
1004 bsls::TimeInterval ti = bsls::SystemTime::now(bslsClockType)
1005 .addDuration(absoluteTime - now);
1007 now = CLOCK::now();
1008 }
1009}
1010#endif
1011
1012inline
1014{
1015 Imp::yield();
1016}
1017
1018 // *** Thread Identification ***
1019
1020inline
1021bool ThreadUtil::areEqual(const Handle& a, const Handle& b)
1022{
1023 // Some implementations (notably pthreads) do not define the result of
1024 // comparing invalid handles. We avoid undefined behavior by explicitly
1025 // checking for invalid handles.
1026
1027 return Imp::INVALID_HANDLE == a
1028 ? (Imp::INVALID_HANDLE == b)
1029 : (Imp::INVALID_HANDLE == b ? false : Imp::areEqual(a, b));
1030}
1031
1032inline
1033bool ThreadUtil::areEqualId(const Id& a, const Id& b)
1034{
1035 return Imp::areEqualId(a, b);
1036}
1037
1038inline
1040{
1041 return Imp::handleToId(threadHandle);
1042}
1043
1044inline
1046{
1047 return Imp::idAsUint64(threadId);
1048}
1049
1050inline
1051int ThreadUtil::idAsInt(const Id& threadId)
1052{
1053 return Imp::idAsInt(threadId);
1054}
1055
1056inline
1058{
1059 return Imp::INVALID_HANDLE;
1060}
1061
1062inline
1063bool ThreadUtil::isEqual(const Handle& a, const Handle& b)
1064{
1065 return Imp::areEqual(a, b);
1066}
1067
1068inline
1069bool ThreadUtil::isEqualId(const Id& a, const Id& b)
1070{
1071 return Imp::areEqualId(a, b);
1072}
1073
1074inline
1077{
1078 return Imp::nativeHandle(handle);
1079}
1080
1081inline
1083{
1084 return Imp::self();
1085}
1086
1087inline
1089{
1090 return Imp::selfId();
1091}
1092
1093inline
1095{
1096 return Imp::selfIdAsInt();
1097}
1098
1099inline
1101{
1102 return Imp::selfIdAsUint64();
1103}
1104
1105 // *** Thread-Specific (Local) Storage (TSS or TLS) ***
1106
1107inline
1108int ThreadUtil::createKey(Key *key, Destructor threadKeyCleanupFunction)
1109{
1110 return Imp::createKey(key, threadKeyCleanupFunction);
1111}
1112
1113inline
1115{
1116 return Imp::deleteKey(key);
1117}
1118
1119inline
1121{
1122 return Imp::getSpecific(key);
1123}
1124
1125inline
1126int ThreadUtil::setSpecific(const Key& key, const void *value)
1127{
1128 return Imp::setSpecific(key, value);
1129}
1130
1131inline
1133{
1134 return Imp::hardwareConcurrency();
1135}
1136
1137} // close package namespace
1138
1139
1140#endif
1141
1142// ----------------------------------------------------------------------------
1143// Copyright 2015 Bloomberg Finance L.P.
1144//
1145// Licensed under the Apache License, Version 2.0 (the "License");
1146// you may not use this file except in compliance with the License.
1147// You may obtain a copy of the License at
1148//
1149// http://www.apache.org/licenses/LICENSE-2.0
1150//
1151// Unless required by applicable law or agreed to in writing, software
1152// distributed under the License is distributed on an "AS IS" BASIS,
1153// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1154// See the License for the specific language governing permissions and
1155// limitations under the License.
1156// ----------------------------- END-OF-FILE ----------------------------------
1157
1158/** @} */
1159/** @} */
1160/** @} */
Definition bslstl_string.h:1281
Definition bslma_allocator.h:457
Definition bslma_managedptr.h:1182
TARGET_TYPE * ptr() const
Definition bslma_managedptr.h:2553
ManagedPtr_PairProxy< TARGET_TYPE, ManagedPtrDeleter > release()
Definition bslma_managedptr.h:2454
Definition bslmt_threadattributes.h:356
bslstl::StringRef threadName() const
Definition bslmt_threadattributes.h:761
SchedulingPolicy
Definition bslmt_threadattributes.h:376
Definition bsls_timeinterval.h:301
BSLS_KEYWORD_CONSTEXPR_CPP14 TimeInterval & addDuration(const std::chrono::duration< REP_TYPE, PERIOD_TYPE > &duration, typename std::enable_if< TimeInterval_DurationTraits< REP_TYPE, PERIOD_TYPE >::k_IMPLICIT_CONVERSION_ENABLED, int >::type *=0)
Definition bsls_timeinterval.h:1226
Definition bslstl_stringref.h:372
#define BSLA_MAYBE_UNUSED
Definition bsla_maybeunused.h:239
void * bslmt_EntryPointFunctorAdapter_invoker(void *argument)
void(* bslmt_KeyDestructorFunction)(void *)
Definition bslmt_threadutil.h:361
void *(* bslmt_ThreadFunction)(void *)
Definition bslmt_threadutil.h:355
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_ASSERT_OPT(X)
Definition bsls_assert.h:1856
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bslmt_barrier.h:344
static Allocator * globalAllocator(Allocator *basicAllocator=0)
Definition bslma_default.h:905
static bsls::TimeInterval durationToTimeInterval(const bsl::chrono::duration< REP_TYPE, PERIOD_TYPE > &duration)
Definition bslmt_chronoutil.h:307
static void allocateAdapter(bslma::ManagedPtr< EntryPointFunctorAdapter< TYPE > > *adapter, const TYPE &invokable, const bslstl::StringRef &threadName, bslma::Allocator *basicAllocator=0)
Definition bslmt_entrypointfunctoradapter.h:395
Definition bslmt_entrypointfunctoradapter.h:221
Definition bslmt_threadutil.h:375
bslmt_ThreadFunction ThreadFunction
Prototype for thread entry-point functions.
Definition bslmt_threadutil.h:396
static void microSleep(int microseconds, int seconds=0)
Definition bslmt_threadutil.h:955
static int create(Handle *handle, const ThreadAttributes &attributes, ThreadFunction function, void *userData)
static bsls::Types::Uint64 selfIdAsInt()
Definition bslmt_threadutil.h:1094
static int create(Handle *handle, ThreadFunction function, void *userData)
Definition bslmt_threadutil.h:813
static Handle self()
Definition bslmt_threadutil.h:1082
static bool areEqualId(const Id &a, const Id &b)
Definition bslmt_threadutil.h:1033
Imp::Handle Handle
Definition bslmt_threadutil.h:385
static bsls::Types::Uint64 selfIdAsUint64()
Definition bslmt_threadutil.h:1100
static Id handleToId(const Handle &threadHandle)
Definition bslmt_threadutil.h:1039
static void getThreadName(bsl::string *threadName)
Definition bslmt_threadutil.h:941
static void sleepUntil(const bsls::TimeInterval &absoluteTime, bsls::SystemClockType::Enum clockType=bsls::SystemClockType::e_REALTIME)
Definition bslmt_threadutil.h:983
static bool isEqualId(const Id &a, const Id &b)
Definition bslmt_threadutil.h:1069
static int detach(Handle &handle)
Definition bslmt_threadutil.h:915
static int idAsInt(const Id &threadId)
Definition bslmt_threadutil.h:1051
static Id selfId()
Definition bslmt_threadutil.h:1088
static int deleteKey(Key &key)
Definition bslmt_threadutil.h:1114
static bool areEqual(const Handle &a, const Handle &b)
Definition bslmt_threadutil.h:1021
Imp::NativeHandle NativeHandle
Platform-specific thread handle type.
Definition bslmt_threadutil.h:388
static int join(Handle &threadHandle, void **status=0)
Definition bslmt_threadutil.h:949
static bool isEqual(const Handle &a, const Handle &b)
Definition bslmt_threadutil.h:1063
static void setThreadName(const bslstl::StringRef &threadName)
Definition bslmt_threadutil.h:961
static int getMaxSchedulingPriority(ThreadAttributes::SchedulingPolicy policy)
Definition bslmt_threadutil.h:934
bslmt_KeyDestructorFunction Destructor
Prototype for thread-specific key destructors.
Definition bslmt_threadutil.h:402
static int createWithAllocator(Handle *handle, ThreadFunction function, void *userData, bslma::Allocator *allocator)
static bsls::Types::Uint64 idAsUint64(const Id &threadId)
Definition bslmt_threadutil.h:1045
static NativeHandle nativeHandle(const Handle &handle)
Definition bslmt_threadutil.h:1076
ThreadUtilImpl< Platform::ThreadPolicy > Imp
Platform-specific implementation type.
Definition bslmt_threadutil.h:381
Imp::Id Id
Definition bslmt_threadutil.h:393
static void sleep(const bsls::TimeInterval &sleepTime)
Definition bslmt_threadutil.h:967
static const Handle & invalidHandle()
Definition bslmt_threadutil.h:1057
static int convertToSchedulingPriority(ThreadAttributes::SchedulingPolicy policy, double normalizedSchedulingPriority)
Imp::Key Key
Thread-specific key type, used to refer to thread-specific storage.
Definition bslmt_threadutil.h:399
static void yield()
Definition bslmt_threadutil.h:1013
static void exit(void *status)
Definition bslmt_threadutil.h:921
static void * getSpecific(const Key &key)
Definition bslmt_threadutil.h:1120
static int getMinSchedulingPriority(ThreadAttributes::SchedulingPolicy policy)
Definition bslmt_threadutil.h:927
static unsigned int hardwareConcurrency()
Definition bslmt_threadutil.h:1132
static int setSpecific(const Key &key, const void *value)
Definition bslmt_threadutil.h:1126
static int createWithAllocator(Handle *handle, const ThreadAttributes &attributes, ThreadFunction function, void *userData, bslma::Allocator *allocator)
static int createKey(Key *key, Destructor threadKeyCleanupFunction)
Definition bslmt_threadutil.h:1108
Enum
Definition bsls_systemclocktype.h:117
@ e_REALTIME
Definition bsls_systemclocktype.h:120
static TimeInterval now(SystemClockType::Enum clockType)
Definition bsls_systemtime.h:175
unsigned long long Uint64
Definition bsls_types.h:137