BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslmt_threadutilimpl_pthread.h
Go to the documentation of this file.
1/// @file bslmt_threadutilimpl_pthread.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslmt_threadutilimpl_pthread.h -*-C++-*-
8#ifndef INCLUDED_BSLMT_THREADUTILIMPL_PTHREAD
9#define INCLUDED_BSLMT_THREADUTILIMPL_PTHREAD
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslmt_threadutilimpl_pthread bslmt_threadutilimpl_pthread
15/// @brief Provide a POSIX implementation of `bslmt::ThreadUtil`.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslmt
19/// @{
20/// @addtogroup bslmt_threadutilimpl_pthread
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslmt_threadutilimpl_pthread-purpose"> Purpose</a>
25/// * <a href="#bslmt_threadutilimpl_pthread-classes"> Classes </a>
26/// * <a href="#bslmt_threadutilimpl_pthread-description"> Description </a>
27/// * <a href="#bslmt_threadutilimpl_pthread-supported-clock-types"> Supported Clock-Types </a>
28/// * <a href="#bslmt_threadutilimpl_pthread-usage"> Usage </a>
29///
30/// # Purpose {#bslmt_threadutilimpl_pthread-purpose}
31/// Provide a POSIX implementation of `bslmt::ThreadUtil`.
32///
33/// # Classes {#bslmt_threadutilimpl_pthread-classes}
34///
35/// - bslmt::ThreadUtilImpl<PosixThreads>: POSIX specialization
36///
37/// @see bslmt_threadutil
38///
39/// # Description {#bslmt_threadutilimpl_pthread-description}
40/// This component provides an implementation of
41/// `bslmt::ThreadUtil` for POSIX threads ("pthreads"),
42/// `bslmt::ThreadUtilImpl<PosixThreads>`, via the template specialization:
43/// @code
44/// bslmt::ThreadUtilImpl<Platform::PosixThreads>
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_pthread-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_pthread-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_pthread
83 * @{
84 */
85
86#include <bslscm_version.h>
87
88#include <bslmt_platform.h>
89
90#ifdef BSLMT_PLATFORM_POSIX_THREADS
91
92// Platform-specific implementation starts here.
93
95
96#include <bsls_platform.h>
98#include <bsls_timeinterval.h>
99#include <bsls_types.h>
100
101#include <bsl_string.h>
102
103#include <pthread.h>
104
105
106
107extern "C" {
108 /// `bslmt_ThreadFunction` is an alias for a function type taking a
109 /// single `void` pointer argument and returning `void *`. Such
110 /// functions are suitable to be specified as thread entry point
111 /// functions to `bslmt::ThreadUtil::create`.
112 typedef void *(*bslmt_ThreadFunction)(void *);
113
114 /// `bslmt_KeyDestructorFunction` is an alias for a function type taking
115 /// a single `void` pointer argument and returning `void`. Such
116 /// functions are suitable to be specified as thread-specific key
117 /// destructor functions to `bslmt::ThreadUtil::createKey`.
118 typedef void (*bslmt_KeyDestructorFunction)(void *);
119}
120
121namespace bslmt {
122
123template <class THREAD_POLICY>
124struct ThreadUtilImpl;
125
126 // ============================================
127 // class ThreadUtilImpl<Platform::PosixThreads>
128 // ============================================
129
130/// This class provides a full specialization of `ThreadUtilImpl` for
131/// pthreads.
132template <>
133struct ThreadUtilImpl<Platform::PosixThreads> {
134
135 // TYPES
136 typedef pthread_t Handle; // thread handle type
137 typedef pthread_t NativeHandle; // native thread handle type
138 typedef pthread_t Id; // thread Id type
139 typedef pthread_key_t Key; // thread-specific storage key type
140
141 // CLASS DATA
142 static const pthread_t INVALID_HANDLE;
143
144 // CLASS METHODS
145 // *** Thread Management ***
146
147 /// Create a new thread of program control having the specified
148 /// `attributes` that invokes the specified `function` with a single
149 /// argument specified by `userData`, and load into the specified
150 /// `threadHandle` an identifier that may be used to refer to the thread
151 /// in future calls to this utility. Return 0 on success, and a
152 /// non-zero value otherwise. The behavior is undefined if the
153 /// specified `thread` is 0 or if `attributes.stackSize()` has been set
154 /// to a negative value other than the unset value. Note that unless
155 /// explicitly "detached" (by `detach`), or unless the
156 /// `BSLMT_CREATE_DETACHED` attribute is specified, a call to `join`
157 /// must be made once the thread terminates to reclaim any system
158 /// resources associated with the newly created identifier.
159 static int create(Handle *threadHandle,
160 const ThreadAttributes& attributes,
161 bslmt_ThreadFunction function,
162 void *userData);
163
164 /// Create a new thread of program control having platform specific
165 /// default attributes (i.e., "stack size", "scheduling priority"), that
166 /// invokes the specified `function` with a single argument specified by
167 /// `userData`, and load into the specified `threadHandle`, an
168 /// identifier that may be used to refer to the thread in future calls
169 /// to this utility. Return 0 on success, and a non-zero value
170 /// otherwise. The behavior is undefined if the `threadHandle` is 0.
171 /// Note that unless explicitly "detached" (`detach`), a call to `join`
172 /// must be made once the thread terminates to reclaim any system
173 /// resources associated with the newly created identifier.
174 static int create(Handle *threadHandle,
175 bslmt_ThreadFunction function,
176 void *userData);
177
178 /// "Detach" the thread identified by the specified `threadHandle`, such
179 /// that when it terminates, the resources associated the thread will
180 /// automatically be reclaimed. Note that once a thread is "detached",
181 /// it is no longer possible to `join` the thread to retrieve the its
182 /// exit status.
183 static int detach(Handle& threadHandle);
184
185 /// Exit the current thread and return the specified `status`. If the
186 /// current thread is not "detached", then a call to `join` must be made
187 /// to reclaim any resources used by the thread, and to retrieve the
188 /// exit status. Note that generally, the preferred method of exiting a
189 /// thread is to return form the entry point function.
190 static void exit(void *status);
191
192 /// Return the maximum available priority for the specified `policy`,
193 /// where `policy` is of type `ThreadAttributes::SchedulingPolicy`.
194 /// Return `ThreadAttributes::BSLMT_UNSET_PRIORITY` if the maximum
195 /// scheduling priority cannot be determined. Note that, for some
196 /// platform / policy combinations, `getMinSchedulingPriority(policy)`
197 /// and `getMaxSchedulingPriority(policy)` return the same value.
198 static int getMaxSchedulingPriority(
200
201 /// Return the minimum available priority for the specified `policy`,
202 /// where `policy` is of type `ThreadAttributes::SchedulingPolicy`.
203 /// Return `ThreadAttributes::BSLMT_UNSET_PRIORITY` if the minimum
204 /// scheduling priority cannot be determined. Note that, for some
205 /// platform / policy combinations, `getMinSchedulingPriority(policy)`
206 /// and `getMaxSchedulingPriority(policy)` return the same value.
207 static int getMinSchedulingPriority(
209
210 /// Load the name of the current thread into the specified `threadName`.
211 /// Note that this method clears `*threadName` on all platforms other
212 /// than Linux and Darwin.
213 static void getThreadName(bsl::string *threadName);
214
215 /// Suspend execution of the current thread until the thread specified
216 /// by `threadHandle` terminates, and reclaim any system resources
217 /// associated with the `threadHandle`. Return 0 on success, and a
218 /// non-zero value otherwise. If the optionally specified `status` is
219 /// not 0, load into the `status` the value returned by the specified
220 /// `thread`.
221 static int join(Handle& threadHandle, void **status = (void**)0);
222
223 /// Suspend execution of the current thread for a period of at least the
224 /// optionally specified `seconds` and `microseconds` (relative time),
225 /// and optionally load into the optionally specified `unsleptTime` the
226 /// amount of time that was not slept by this function if the operation
227 /// was interrupted by a signal. Return 0 on success, and non-zero if
228 /// the operation was interrupted by a signal. Note that the actual
229 /// time suspended depends on many factors including system scheduling,
230 /// and system timer resolution. Note that the actual time suspended
231 /// depends on many factors including system scheduling, and system
232 /// timer resolution.
233 static int microSleep(int microseconds,
234 int seconds = 0,
235 bsls::TimeInterval *unsleptTime = 0);
236
237 /// Set the name of the current thread to the specified `threadName`.
238 /// On all platforms other than Linux and Darwin this method has no
239 /// effect. Note that on those two platforms `threadName` will be
240 /// truncated to a length of 15 bytes, not including the terminating
241 /// '\0'.
242 static void setThreadName(const bslstl::StringRef& threadName);
243
244 /// Suspend execution of the current thread for a period of at least the
245 /// specified `sleepTime` (relative time), and optionally load into the
246 /// optionally specified `unsleptTime` the amount of time that was not
247 /// slept by this function if the operation was interrupted by a signal.
248 /// Return 0 on success, and a non-zero value if the operation was
249 /// interrupted by a signal. Note that the actual time suspended
250 /// depends on many factors including system scheduling, and system
251 /// timer resolution.
252 static int sleep(const bsls::TimeInterval& sleepTime,
253 bsls::TimeInterval *unsleptTime = 0);
254
255 /// Suspend execution of the current thread until the specified
256 /// `absoluteTime`. Optionally specify `clockType` which determines the
257 /// epoch from which the interval `absoluteTime` is measured (see
258 /// {Supported Clock-Types} in the component documentation). Return 0
259 /// on success, and a non-zero value otherwise. The behavior is
260 /// undefined unless `absoluteTime` represents a time after January 1,
261 /// 1970 and before the end of December 31, 9999 (i.e., a time interval
262 /// greater than or equal to 0, and less than 253,402,300,800 seconds).
263 /// Note that the actual time suspended depends on many factors
264 /// including system scheduling and system timer resolution.
265 static int sleepUntil(const bsls::TimeInterval& absoluteTime,
268
269 /// Suspend execution of the current thread until the specified
270 /// `absoluteTime`. Optionally specify `retryOnSignalInterrupt`
271 /// indicating whether to put this thread to sleep again if the
272 /// operating system interrupts the sleep because of a signal.
273 /// Optionally specify `clockType` which determines the epoch from which
274 /// the interval `absoluteTime` is measured (see {Supported
275 /// Clock-Types} in the component documentation). Return 0 on success,
276 /// and a non-zero value otherwise. If `retryOnSignalInterrupt` is
277 /// `true`, an interrupt from a signal will be ignored and the current
278 /// the thread will be put back to sleep until `absoluteTime`, otherwise
279 /// this call will return 0 to the calling thread immediately. The
280 /// behavior is undefined unless `absoluteTime` represents a time after
281 /// January 1, 1970 and before the end of December 31, 9999 (i.e., a
282 /// time interval greater than or equal to 0, and less than
283 /// 253,402,300,800 seconds). Note that the actual time suspended
284 /// depends on many factors including system scheduling and system timer
285 /// resolution.
286 static int sleepUntil(const bsls::TimeInterval& absoluteTime,
287 bool retryOnSignalInterrupt
288 = false,
291
292 /// Put the current thread to the end of the scheduler's queue and
293 /// schedule another thread to run. This allows cooperating threads of
294 /// the same priority to share CPU resources equally.
295 static void yield();
296
297 // *** Thread Identification ***
298
299 /// Return `true` if the specified `a` and `b` thread handles, identify
300 /// the same thread, and `false` otherwise.
301 static bool areEqual(const Handle& a, const Handle& b);
302
303 /// Return `true` if the specified `a` and `b` thread id identify the
304 /// same thread, and `false` otherwise.
305 static bool areEqualId(const Id& a, const Id& b);
306
307 /// Return the unique integral identifier of a thread uniquely
308 /// identified by the specified `threadId` within the current process.
309 /// Note that this representation is particularly useful for logging
310 /// purposes. Also note that this value is only valid until the thread
311 /// terminates and may be reused thereafter.
312 static bsls::Types::Uint64 idAsUint64(const Id& threadId);
313
314 /// Return the unique integral identifier of a thread uniquely
315 /// identified by the specified `threadId` within the current process.
316 /// Note that this representation is particularly useful for logging
317 /// purposes. Also note that this value is only valid until the thread
318 /// terminates and may be reused thereafter.
319 ///
320 /// DEPRECATED: use `idAsUint64`.
321 static int idAsInt(const Id& threadId);
322
323 /// Return the platform specific identifier associated with the thread
324 /// specified by `threadHandle`. Note that the returned native handle
325 /// may not be a globally unique identifier for the thread (see
326 /// `selfIdAsUint`).
327 static NativeHandle nativeHandle(const Handle& threadHandle);
328
329 /// Return an identifier that can be used to refer to the current thread
330 /// in future calls to this utility.
331 static Handle self();
332
333 /// Return an identifier that can be used to uniquely identify the
334 /// current thread within the current process. Note that the id is only
335 /// valid until the thread terminates and may be reused thereafter.
336 static Id selfId();
337
338 /// Return an integer of the unique identifier of the current thread
339 /// within the current process. This representation is particularly
340 /// useful for logging purposes. Note that this value is only valid
341 /// until the thread terminates and may be reused thereafter.
342 ///
343 /// DEPRECATED: Use `selfIdAsUint64` instead.
344 static bsls::Types::Uint64 selfIdAsInt();
345
346 /// Return an integer of the unique identifier of the current thread
347 /// within the current process. This representation is particularly
348 /// useful for logging purposes. Note that this value is only valid
349 /// until the thread terminates and may be reused thereafter.
350 static bsls::Types::Uint64 selfIdAsUint64();
351
352 /// Return the unique identifier of the thread having the specified
353 /// `threadHandle` within the current process. Note that this value is
354 /// only valid until the thread terminates and may be reused thereafter.
355 static Id handleToId(const Handle& threadHandle);
356
357 // *** Thread-Specific (Local) Storage (TSS or TLS) ***
358
359 /// Load, into the specified `key`, an identifier that can be used to
360 /// store (`setSpecific`) and retrieve (`getSpecific`) a single
361 /// thread-specific pointer value. Associate with the identifier, the
362 /// specified `destructor` if a non-zero value is specified. Return 0
363 /// on success, and a non-zero value otherwise.
364 static int createKey(Key *key, bslmt_KeyDestructorFunction destructor);
365
366 /// Delete the specified thread-specific `key`. Return 0 on success,
367 /// and a non-zero value otherwise. Note that deleting a key does not
368 /// delete any data that is currently associated with the key in the
369 /// calling thread or any other thread.
370 static int deleteKey(Key& key);
371
372 /// Return the value associated with the specified thread-specific
373 /// `key`. Note that if the key is not valid, a value of zero is
374 /// returned, which is indistinguishable from a valid key with a 0
375 /// value.
376 static void *getSpecific(const Key& key);
377
378 /// Associate the specified `value` with the specified thread-specific
379 /// `key`. Return 0 on success, and a non-zero value otherwise. TBD
380 /// elaborate on what `value` represents
381 static int setSpecific(const Key& key, const void *value);
382
383 /// Return the number of concurrent threads supported by the
384 /// implementation on success, and 0 otherwise.
385 static unsigned int hardwareConcurrency();
386};
387
388// ============================================================================
389// INLINE DEFINITIONS
390// ============================================================================
391
392 // --------------------------------------------
393 // class ThreadUtilImpl<Platform::PosixThreads>
394 // --------------------------------------------
395
396// CLASS METHODS
397 // *** Thread Management ***
398inline
399int ThreadUtilImpl<bslmt::Platform::PosixThreads>::create(
400 Handle *threadHandle,
401 bslmt_ThreadFunction function,
402 void *userData)
403{
404 ThreadAttributes attr;
405 return create(threadHandle, attr, function, userData);
406}
407
408inline
409int ThreadUtilImpl<bslmt::Platform::PosixThreads>::detach(Handle& threadHandle)
410{
411 return pthread_detach(threadHandle);
412}
413
414inline
415void ThreadUtilImpl<bslmt::Platform::PosixThreads>::exit(void *status)
416{
417 pthread_exit(status);
418}
419
420inline
421int ThreadUtilImpl<bslmt::Platform::PosixThreads>::join(Handle& threadHandle,
422 void **status)
423{
424 return pthread_join(threadHandle, status);
425}
426
427inline
428int ThreadUtilImpl<bslmt::Platform::PosixThreads>::sleepUntil(
429 const bsls::TimeInterval& absoluteTime,
431{
432 return sleepUntil(absoluteTime, false, clockType);
433}
434
435inline
436void ThreadUtilImpl<bslmt::Platform::PosixThreads>::yield()
437{
438 sched_yield();
439}
440
441 // *** Thread Identification ***
442
443inline
444bool ThreadUtilImpl<bslmt::Platform::PosixThreads>::areEqual(const Handle& a,
445 const Handle& b)
446{
447 return pthread_equal(a, b);
448}
449
450inline
451bool ThreadUtilImpl<bslmt::Platform::PosixThreads>::areEqualId(const Id& a,
452 const Id& b)
453{
454 return pthread_equal(a, b);
455}
456
457inline
458ThreadUtilImpl<bslmt::Platform::PosixThreads>::Id
459ThreadUtilImpl<bslmt::Platform::PosixThreads>::handleToId(
460 const Handle& threadHandle)
461{
462 return threadHandle;
463}
464
465inline
467ThreadUtilImpl<bslmt::Platform::PosixThreads>::idAsUint64(const Id& threadId)
468{
469#ifdef BSLS_PLATFORM_OS_DARWIN
470 return reinterpret_cast<bsls::Types::Uint64>(threadId);
471#else
472 return static_cast<bsls::Types::Uint64>(threadId);
473#endif
474}
475
476inline
477int
478ThreadUtilImpl<bslmt::Platform::PosixThreads>::idAsInt(const Id& threadId)
479{
480 // Our interface is not good if the id is a pointer. The two casts will
481 // avoid a compilation error though. TBD
482
483 return static_cast<int>(idAsUint64(threadId));
484}
485
486inline
487ThreadUtilImpl<bslmt::Platform::PosixThreads>::NativeHandle
488ThreadUtilImpl<bslmt::Platform::PosixThreads>::nativeHandle(
489 const Handle& threadHandle)
490{
491 return threadHandle;
492}
493
494inline
495ThreadUtilImpl<bslmt::Platform::PosixThreads>::Handle
496ThreadUtilImpl<bslmt::Platform::PosixThreads>::self()
497{
498 return pthread_self();
499}
500
501inline
502ThreadUtilImpl<bslmt::Platform::PosixThreads>::Id
503ThreadUtilImpl<bslmt::Platform::PosixThreads>::selfId()
504{
505 return pthread_self();
506}
507
508inline
510ThreadUtilImpl<bslmt::Platform::PosixThreads>::selfIdAsInt()
511{
512 return idAsInt(selfId());
513}
514
515inline
517ThreadUtilImpl<bslmt::Platform::PosixThreads>::selfIdAsUint64()
518{
519 return idAsUint64(selfId());
520}
521
522 // *** Thread-Specific (Local) Storage (TSS or TLS) ***
523
524inline
525int ThreadUtilImpl<bslmt::Platform::PosixThreads>::createKey(
526 Key *key,
528{
529 return pthread_key_create(key,destructor);
530}
531
532inline
533int ThreadUtilImpl<bslmt::Platform::PosixThreads>::deleteKey(Key& key)
534{
535 return pthread_key_delete(key);
536}
537
538inline
539void *ThreadUtilImpl<bslmt::Platform::PosixThreads>::getSpecific(
540 const Key& key)
541{
542 return pthread_getspecific(key);
543}
544
545inline
546int ThreadUtilImpl<bslmt::Platform::PosixThreads>::setSpecific(
547 const Key& key,
548 const void *value)
549{
550 return pthread_setspecific(key, value);
551}
552
553} // close package namespace
554
555
556#endif // BSLMT_PLATFORM_POSIX_THREADS
557
558#endif
559
560// ----------------------------------------------------------------------------
561// Copyright 2015 Bloomberg Finance L.P.
562//
563// Licensed under the Apache License, Version 2.0 (the "License");
564// you may not use this file except in compliance with the License.
565// You may obtain a copy of the License at
566//
567// http://www.apache.org/licenses/LICENSE-2.0
568//
569// Unless required by applicable law or agreed to in writing, software
570// distributed under the License is distributed on an "AS IS" BASIS,
571// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
572// See the License for the specific language governing permissions and
573// limitations under the License.
574// ----------------------------- END-OF-FILE ----------------------------------
575
576/** @} */
577/** @} */
578/** @} */
Definition bslstl_string.h:1281
SchedulingPolicy
Definition bslmt_threadattributes.h:376
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
Definition bslmt_barrier.h:344
Enum
Definition bsls_systemclocktype.h:117
@ e_REALTIME
Definition bsls_systemclocktype.h:120
unsigned long long Uint64
Definition bsls_types.h:137