BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslmt_threadutil

Typedefs

typedef void *(* bslmt_ThreadFunction) (void *)
 
typedef void(* bslmt_KeyDestructorFunction) (void *)
 

Detailed Description

Outline

Purpose

Provide platform-independent utilities related to threading.

Classes

See also
bslmt_threadattributes, bslmt_configuration

Description

This component defines a utility struct, bslmt::ThreadUtil, that serves as a name space for a suite of pure functions to create threads, join them (make one thread block and wait for another thread to exit), manipulate thread handles, manipulate the current thread, and (on some platforms) access thread-local storage.

Creating a Simple Thread with Default Attributes

Clients call bslmt::ThreadUtil::create() to create threads. Threads may be started using a "C" linkage function pointer (of a type defined by bslmt::ThreadUtil::ThreadFunction) and a void pointer to userData to be passed to the function; or an "invokable" object of parameterized type (any copy-constructible type on which operator() may be invoked). The invoked function becomes the main driver for the new thread; when it returns, the thread terminates.

Thread Identity

A thread is identified by an object of the opaque type bslmt::ThreadUtil::Handle. A handle of this type is returned when a thread is created (using bslmt::ThreadUtil::create). A client can also retrieve a Handle for the "current" thread via the self method:

static Handle self()
Definition bslmt_threadutil.h:1082
Imp::Handle Handle
Definition bslmt_threadutil.h:385

Several thread manipulation functions in bslmt::ThreadUtil take a thread handle, or pointer to a thread handle, as an argument. To facilitate compatibility with existing systems and allow for non-portable operations, clients also have access to the bslmt::ThreadUtil::NativeHandle type, which exposes the underlying, platform-specific thread identifier type:

Imp::NativeHandle NativeHandle
Platform-specific thread handle type.
Definition bslmt_threadutil.h:388
static NativeHandle nativeHandle(const Handle &handle)
Definition bslmt_threadutil.h:1076

Note that the returned native handle may not be a globally unique identifier for the thread, and, e.g., should not be converted to an integer identifier, or used as a key in a map.

Setting Thread Priorities

bslmt::ThreadUtil allows clients to configure the priority of newly created threads by setting the inheritSchedule, schedulingPolicy, and schedulingPriority of a thread attributes object supplied to the create method. The range of legal values for schedulingPriority depends on both the platform and the value of schedulingPolicy, and can be obtained from the getMinSchedulingPriority and getMaxSchedulingPriority methods. Both schedulingPolicy and schedulingPriority are ignored unless inheritSchedule is false (the default value is true). Note that not only is effective setting of thread priorities workable on only some combinations of platforms and user privileges, but setting the thread policy and priority appropriately for one platform may cause thread creation to fail on another platform. Also note that an unset thread priority may be interpreted as being outside the valid range defined by [ getMinSchedulingPriority(policy), getMaxSchedulingPriority(policy) ].

Platform Restrictions
------------ --------------------------------------------------------------
Solaris 5.10 None.
Solaris 5.11 Spawning of threads fails if `schedulingPolicy` is
`BSLMT_SCHED_FIFO` or `BSLMT_SCHED_RR`. Thread priorities
should not be used on Solaris 5.11 as it is not clear that
they have any detectable effect. Note that
`getMinSchedulingPriority` and `getMaxSchedulingPriority`
return different values than on Solaris 5.10.
AIX For non-privileged clients, spawning of threads fails if
`schedulingPolicy` is `BSLMT_SCHED_FIFO` or `BSLMT_SCHED_RR`.
Linux Non-privileged clients *can* *not* make effective use of
thread priorities -- spawning of threads fails if
`schedulingPolicy` is `BSLMT_SCHED_FIFO` or `BSLMT_SCHED_RR`,
and `getMinSchedulingPriority == getMaxSchedulingPriority` if
the policy has any other value.
Darwin Non-privileged clients *can* *not* make effective use of
thread priorities -- there is no observable difference in
urgency between high priority and low priority threads.
Spawning of threads does succeed, however, for all scheduling
policies.
Windows Clients *can* *not* make effective use of thread priorities --
`schedulingPolicy`, `schedulingPriority`, and
`inheritSchedule` are ignored for all clients.

Supported Clock-Types

bsls::SystemClockType supplies the enumeration indicating the system clock on which timeouts supplied to other methods should be based. If the clock type indicated at construction is bsls::SystemClockType::e_REALTIME, the absTime argument passed to the timedWait method of the various synchronization primitives offered in bslmt should be expressed as an absolute offset since 00:00:00 UTC, January 1, 1970 (which matches the epoch used in bsls::SystemTime::now(bsls::SystemClockType::e_REALTIME). If the clock type indicated at construction is bsls::SystemClockType::e_MONOTONIC, the absTime argument passed to the timedWait method of the various synchronization primitives offered in bslmt should be expressed as an absolute offset since the epoch of this clock (which matches the epoch used in bsls::SystemTime::now(bsls::SystemClockType::e_MONOTONIC).

Usage

This section illustrates the intended use of this component.

Example 1: Creating a Simple Thread with Default Attributes

In this example, we create a thread using the default attribute settings. Upon creation, the thread executes the user-supplied C-linkage function myThreadFunction that counts 5 seconds before terminating:

First, we create a function that will run in the spawned thread:

/// Print to standard output "Another second has passed" every second
/// for five seconds, and return 0.
extern "C" void *myThreadFunction(void *)
{
for (int i = 0; i < 3; ++i) {
bsl::cout << "Another second has passed." << bsl::endl;
}
return 0;
}
static void microSleep(int microseconds, int seconds=0)
Definition bslmt_threadutil.h:955

Now, we show how to create and join the thread.

After creating the thread, the main routine joins the thread, which, in effect, causes main to wait for execution of myThreadFunction to complete, and guarantees that the output from main will follow the last output from the user-supplied function:

int main()
{
attr.setStackSize(1024 * 1024);
int rc = bslmt::ThreadUtil::create(&handle, attr, myThreadFunction, 0);
assert(0 == rc);
assert(0 == rc);
bsl::cout << "A three second interval has elapsed\n";
return 0;
}
Definition bslmt_threadattributes.h:356
ThreadAttributes & setStackSize(int value)
Definition bslmt_threadattributes.h:703
static void setDefaultThreadStackSize(int numBytes)
static int recommendedDefaultThreadStackSize()
static int create(Handle *handle, ThreadFunction function, void *userData)
Definition bslmt_threadutil.h:813
static int join(Handle &threadHandle, void **status=0)
Definition bslmt_threadutil.h:949
static void yield()
Definition bslmt_threadutil.h:1013

Finally, the output of this program is:

Another second has passed.
Another second has passed.
Another second has passed.
A three second interval has elapsed.

Example 2: Creating a Simple Thread with User-Specified Attributes

In this example, we will choose to override the default thread attribute values.

The attributes of a thread can be specified explicitly by supplying a bslmt::ThreadAttributes object to the create method. For instance, we could specify a smaller stack size for a thread to conserve system resources if we know that we will require not require the platform's default stack size.

First, we define our thread function, noting that it doesn't need much stack space:

/// Initialize a small object on the stack and do some work.
extern "C" void *mySmallStackThreadFunction(void *threadArg)
{
char *initValue = (char *)threadArg;
char Small[8];
bsl::memset(&Small[0], *initValue, 8);
// do some work ...
return 0;
}

Finally, we show how to create a detached thread running the function just created with a small stack size:

/// Create a detached thread with a small stack size and perform some work.
void createSmallStackSizeThread()
{
enum { k_STACK_SIZE = 16384 };
attributes.setDetachedState(
attributes.setStackSize(k_STACK_SIZE);
char initValue = 1;
int status = bslmt::ThreadUtil::create(&handle,
attributes,
mySmallStackThreadFunction,
&initValue);
}
@ e_CREATE_DETACHED
Definition bslmt_threadattributes.h:366
ThreadAttributes & setDetachedState(DetachedState value)
Definition bslmt_threadattributes.h:651

Example 3: Setting Thread Priorities

In this example we demonstrate creating 3 threads with different priorities. We use the convertToSchedulingPriority function to translate a normalized, floating-point priority in the range [ 0.0, 1.0 ] to an integer priority in the range [ getMinSchedulingPriority, getMaxSchedulingPriority ] to set the schedulingPriority attribute.

/// Create 3 threads with different priorities and then wait for them
/// all to finish.
void runSeveralThreads()
{
enum { k_NUM_THREADS = 3 };
bslmt::ThreadUtil::Handle handles[k_NUM_THREADS];
bslmt_ThreadFunction functions[k_NUM_THREADS] = {
MostUrgentThreadFunctor,
FairlyUrgentThreadFunctor,
LeastUrgentThreadFunctor };
double priorities[k_NUM_THREADS] = { 1.0, 0.5, 0.0 };
attributes.setInheritSchedule(false);
attributes.setSchedulingPolicy(policy);
for (int i = 0; i < k_NUM_THREADS; ++i) {
priorities[i]));
int rc = bslmt::ThreadUtil::create(&handles[i],
attributes,
functions[i], 0);
assert(0 == rc);
}
for (int i = 0; i < k_NUM_THREADS; ++i) {
int rc = bslmt::ThreadUtil::join(handles[i]);
assert(0 == rc);
}
}
SchedulingPolicy
Definition bslmt_threadattributes.h:376
@ e_SCHED_OTHER
Definition bslmt_threadattributes.h:380
ThreadAttributes & setInheritSchedule(bool value)
Definition bslmt_threadattributes.h:675
ThreadAttributes & setSchedulingPriority(int value)
Definition bslmt_threadattributes.h:695
ThreadAttributes & setSchedulingPolicy(SchedulingPolicy value)
Definition bslmt_threadattributes.h:683
void *(* bslmt_ThreadFunction)(void *)
Definition bslmt_threadutil.h:355
static int convertToSchedulingPriority(ThreadAttributes::SchedulingPolicy policy, double normalizedSchedulingPriority)

Typedef Documentation

◆ bslmt_KeyDestructorFunction

typedef void(* bslmt_KeyDestructorFunction) (void *)

bslmt_KeyDestructorFunction is an alias for a function type taking a single void pointer argument and returning void. Such functions are suitable to be specified as thread-specific key destructor functions to bslmt::ThreadUtil::createKey.

◆ bslmt_ThreadFunction

typedef void *(* bslmt_ThreadFunction) (void *)

bslmt_ThreadFunction is an alias for a function type taking a single void pointer argument and returning void *. Such functions are suitable to be specified as thread entry-point functions to bslmt::ThreadUtil::create. Note that create also accepts any invokable C++ "functor" object.