Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component bslmt_threadattributes
[Package bslmt]

Provide a description of the attributes of a thread. More...

Namespaces

namespace  bslmt

Detailed Description

Outline
Purpose:
Provide a description of the attributes of a thread.
Classes:
bslmt::ThreadAttributes description of the attributes of a thread
See also:
Component bslmt_threadutil, Component bslmt_configuration
Description:
This component provides a simply constrained (value-semantic) attribute class, bslmt::ThreadAttributes, for describing attributes of a thread in a platform-independent way.
The default values and constraints for the attributes provided by bslmt::ThreadAttributes are listed in the following two tables:
  Name                Type                   Default
  ------------------  ---------------------  ----------------------
  detachedState       enum DetachedState     e_CREATE_JOINABLE
  stackSize           int                    e_UNSET_STACK_SIZE
  guardSize           int                    e_UNSET_GUARD_SIZE
  inheritSchedule     bool                   'true'
  schedulingPolicy    enum SchedulingPolicy  e_SCHED_DEFAULT
  schedulingPriority  int                    e_UNSET_PRIORITY
  threadName          bsl::string            ""

  Name          Constraint
  ---------     ---------------------------------------------------
  stackSize     'e_UNSET_STACK_SIZE == stackSize || 0 <= stackSize'
  guardSize     'e_UNSET_GUARD_SIZE == guardSize || 0 <= guardSize'
detachedState Attribute:
The detachedState attribute indicates whether an associated thread should be created in a joinable or detached state, through the enum values e_CREATE_JOINABLE and e_CREATE_DETACHED, respectively. A thread in the joinable state will have its exit status maintained after thread termination. Any thread can join with a joinable thread (see bslmt_threadutil), in which case the joining thread will block, waiting for the joined thread's execution to complete, after which the joined thread's termination status will be reported back to the joining thread, and its resources reclaimed. A thread in a detached state will have its resources claimed at thread termination, and cannot be joined. Note that a joinable thread can be made detached after it is created, but not vice versa.
stackSize Attribute:
The stackSize attribute indicates the size, in bytes, of the stack that should be provided to a newly created thread. If the stack size is e_UNSET_STACK_SIZE then a created thread will be provided a default stack size (see bslmt_configuration). The stackSize attribute should be interpreted to mean that a created thread can safely define an automatic variable of the configured stackSize bytes in its thread-entry function. Note that, on some platforms, an adjusted value derived from the stackSize attribute may be supplied to the underlying representation by the thread creation function.
guardSize Attribute:
The guardSize attribute indicates the size of the memory region to provide past the end of a created thread's stack to protect against stack overflows. If a thread's stack pointer overflows into a guard area, the task will receive an error (e.g., a signal). If guardSize is e_UNSET_GUARD_SIZE, then a created thread will be provided with a default native guard size (see bslmt_configuration). Note that the interpretation of guardSize may vary among platforms, and the value may be adjusted up (e.g., by rounding up to a multiple of page size) or ignored entirely (e.g., the Windows platform does not support this attribute).
inheritSchedule Attribute:
The inheritSchedule attribute, if true, indicates that a created thread's schedulingPolicy and schedulingPriority attributes should be taken from its parent thread and the configured values of those thread attributes should be ignored. If inheritSchedule is false, then the schedulingPolicy and schedulingPriority attribute values should be used to configure a thread. See bslmt_threadutil for information about support for this attribute.
schedulingPolicy Attribute:
The schedulingPolicy attribute indicates the policy that should be used to schedule the created thread for execution. Typically clients should use the default platform supplied scheduling policy, which is indicated by the e_SCHED_DEFAULT value. The alternative scheduling policies, e_THREAD_FIFO and e_SCHED_RR, are "real-time" scheduling policies, and may not be available unless the task is run with the appropriate privileges. e_SCHED_FIFO indicates a thread should run until it either yields or is interrupted by a thread of higher priority. e_SCHED_RR is the same as e_SCHED_FIFO, except that the created thread may be interrupted by a ready thread of equal priority after a finite time-slice. This attribute is ignored unless inheritSchedule is false. See bslmt_threadutil for information about support for this attribute.
schedulingPriority Attribute:
The schedulingPriority attribute is a platform specific value whose valid values range from the minimum to the maximum value for the associated schedulingPolicy, with higher numbers indicating a more urgent priority. Functions to obtain the minimum and maximum values are in this component and bslmt_threadutil. This attribute is ignored unless inheritSchedule is false. See bslmt_threadutil for information about support for this attribute.
threadName Attribute:
The threadName attribute indicates the name the thread is to have. Thread names show up in debuggers on some platforms, and are unsupported on others. Thread names have unlimited lengths in a thread attributes object, but the thread names actually supported by specific platforms may have limited length, depending upon the platform, so thread names may be truncated when assigned to the actual thread. At this time, only Linux and Darwin support thread names, and there is a maximum thread name length of 15 on both of those platforms.
Fluent Interface:
bslmt::ThreadAttributes provides manipulators that return a non-'const' reference to the object so that setting individual attributes can be "chained" into a single expression statement, or that attributes can be "built" in place as a function argument. For example:
  bslmt::ThreadUtil::Handle handle;

  int status = bslmt::ThreadUtil::create(
                          &handle,
                          bslmt::ThreadAttributes().setThreadName("myName")
                                                   .setInheritSchedule(true),
                          myThreadFunction,
                          &myThreadArgument);
Usage:
This section illustrates intended use of this component.
Example 1: Creating and Modifying Thread Attributes Objects:
In this example we will demonstrate creating and configuring a bslmt::ThreadAttributes object, then using it with a hypothetical thread-creation function. Finally we show how a thread creation function might interpret those attributes for the underlying operating system.
First we forward declare a routine that we will use to create a thread:
  void myThreadCreate(int                             *threadHandle,
                      const bslmt::ThreadAttributes&   attributes,
                      void                           (*function)());
      // Spawn a thread having properties described by the specified
      // 'attributes' and that runs the specified 'function', and assign a
      // handle referring to the spawned thread to the specified
      // '*threadHandle'.
Then, we declare two routines that will return the minimum and maximum thread priority given a scheduling policy. Note that similar methods exist in bslmt_threadutil.
  int myMinPriority(bslmt::ThreadAttributes::SchedulingPolicy policy);
  int myMaxPriority(bslmt::ThreadAttributes::SchedulingPolicy policy);
Next we define a function that we will use as our thread entry point. This function declares a single variable on the stack of predetermined size.
  enum { k_BUFFER_SIZE = 128 * 1024 };

  void myThreadFunction()
  {
      int bufferLocal[k_BUFFER_SIZE];

      // Perform some calculation that involves no subroutine calls or
      // additional automatic variables.
  }
Then, we define our main function, in which we demonstrate configuring a bslmt::ThreadAttributes object describing the properties a thread we will create.
  void testMain()
  {
Next, we create a thread attributes object, attributes, and set its stackSize attribute to a value large enough to accommodate the BUFFER_SIZE buffer used by myThreadFunction. Note that we use BUFFER_SIZE as an illustration; in practice, it is difficult or impossible to gauge the exact amount of stack size required for a typical thread, and the value supplied should be a reasonable upper bound on the anticipated requirement.
      bslmt::ThreadAttributes attributes;
      attributes.setStackSize(k_BUFFER_SIZE);
Then, we set the detachedState property to e_CREATE_DETACHED, indicating that the thread will not be joinable, and its resources will be reclaimed upon termination. Now, we create a thread, using the attributes configured above:
      int handle;
      myThreadCreate(&handle, attributes, &myThreadFunction);
  }
Finally, we define the thread creation function, and show how a thread attributes object might be interpreted by it:
  void myThreadCreate(int                             *threadHandle,
                      const bslmt::ThreadAttributes&   attributes,
                      void                           (*function)())
      // Spawn a thread with properties described by the specified
      // 'attributes', running the specified 'function', and assign a handle
      // referring to the spawned thread to the specified '*threadHandle'.
  {
      int stackSize = attributes.stackSize();
      if (bslmt::ThreadAttributes::e_UNSET_STACK_SIZE == stackSize) {
          stackSize = bslmt::Configuration::defaultThreadStackSize();
      }

      // Add a "fudge factor" to 'stackSize' to ensure that the client can
      // declare an object of 'stackSize' bytes on the stack safely.

      stackSize += 8192;

      int guardSize = attributes.guardSize();
      if (bslmt::ThreadAttributes::e_UNSET_GUARD_SIZE == guardSize) {
          guardSize = bslmt::Configuration::nativeDefaultThreadGuardSize();
      }

      int policy = attributes.schedulingPolicy();
      int priority = attributes.schedulingPriority();

      // the following is pseudo-code for actually creating the thread
      /*
      if (bslmt::ThreadAttributes::e_UNSET_PRIORITY == priority) {
          priority = operatingSystemDefaultPriority(policy);
      }

      operatingSystemThreadCreate(threadHandle,
                                  stackSize,
                                  guardSize,
                                  attributes.inheritSchedule(),
                                  policy,
                                  priority,
                                  attributes.detachedState()
                                  function);
      */
  }
Notice that a new value derived from the stackSize attribute is used so that the meaning of the attribute is platform neutral.