Quick Links:

bal | bbl | bdl | bsl

Namespaces | Functions

Component bslmt_entrypointfunctoradapter
[Package bslmt]

Provide types and utilities to simplify thread creation. More...

Namespaces

namespace  bslmt

Functions

void * bslmt_EntryPointFunctorAdapter_invoker (void *argument)

Detailed Description

Outline
Purpose:
Provide types and utilities to simplify thread creation.
Classes:
EntryPointFunctorAdapter Encapsulate invokable object with allocator.
EntryPointFunctorAdapterUtil Dynamic allocation of adapter objects.
Description:
This component defines a type, EntryPointFunctorAdapter, that contains a single instance of a parameterized invokable type along with an allocator to manage it. The parameterized type must provide a copy constructor and void operator()().
This component also provides a C-linkage function bslmt_EntryPointFunctorAdapter_invoker that operates on a pointer to EntryPointFunctorAdapter, invoking the invokable object contained within it and then deallocating the adapter object along with the contained invokable object. Together, EntryPointFunctorAdapter and bslmt_EntryPointFunctorAdapter_invoker simplify the process of invoking a generic functor as a C-style callback, such as a thread entry point.
Finally, this component provides EntryPointFunctorAdapterUtil, a namespace for a utility function that dynamically allocates instances of EntryPointFunctorAdapter.
Usage:
This section illustrates the intended use of this component.
Example 1: Wrapping a C++ Invokable Type:
Suppose we have an existing interface for invoking a C-linkage function and passing a void* argument to it. This situation may arise when starting threads or in general when registering a C-style callback. A simplistic example of such a function is:
  extern "C" {
     typedef void *(*CallbackFunction)(void*);
  }

  void *executeWithArgument(CallbackFunction funcPtr, void *argument)
  {
     return funcPtr(argument);
  }
In this example, we want to use this interface to invoke a C++-style functor. Our approach will be to use bslmt_EntryPointFunctorAdapter_invoker as the C-linkage callback function, and a dynamically allocated value of EntryPointFunctorAdapter as the void* argument.
First, we define a C++ functor type. This type implements the job of counting the number of words in a string held by value.
  class WordCountJob {
      // DATA
      bsl::string  d_message;
      int         *d_result_p; // held, not owned

    public:
      // TRAITS
      BSLMF_NESTED_TRAIT_DECLARATION(WordCountJob,
                                     bslma::UsesBslmaAllocator);

      // CREATORS
      WordCountJob(const bslstl::StringRef&  message,
                   int                      *result,
                   bslma::Allocator         *basicAllocator = 0);
          // Create a new functor that, upon execution, counts the number of
          // words (contiguous sequences of non-space characters) in the
          // specified 'message' and stores the count in the specified
          // 'result' address.  Optionally specify a 'basicAllocator' used to
          // supply memory.  If 'basicAllocator' is 0, the currently
          // installed default allocator is used.

      WordCountJob(const WordCountJob&  original,
                   bslma::Allocator    *basicAllocator = 0);
          // Create a new functor that performs the same calculation as the
          // specified 'other' functor.  Optionally specify a
          // 'basicAllocator' used to supply memory.  If 'basicAllocator' is
          // 0, the currently installed default allocator is used.

      // MANIPULATORS
      void operator()();
          // Count the number of words in the message and store the count in
          // the address specified on construction.
  };

  inline
  WordCountJob::WordCountJob(const bslstl::StringRef&  message,
                             int                      *result,
                             bslma::Allocator         *basicAllocator)
  : d_message(message, basicAllocator)
  , d_result_p(result)
  {}

  inline
  WordCountJob::WordCountJob(const WordCountJob&  original,
                             bslma::Allocator    *basicAllocator)
  : d_message(original.d_message, basicAllocator)
  , d_result_p(original.d_result_p)
  {}

  void WordCountJob::operator()()
  {
      bool inWord = false;
      *d_result_p = 0;
      for (unsigned i = 0; i < d_message.length(); ++i) {
          if (isspace(d_message[i])) {
              inWord = false;
          } else if (!inWord) {
              inWord = true;
              ++(*d_result_p);
          }
      }
  }
Next, we dynamically allocate an EntryPointFunctorAdapter wrapping an instance of this functor:
  int result = 0;
  WordCountJob job("The quick brown fox jumped over the lazy dog.",
                   &result);

  bslma::ManagedPtr<
      bslmt::EntryPointFunctorAdapter<WordCountJob> > threadData;
  bslmt::EntryPointFunctorAdapterUtil::allocateAdapter(&threadData,
                                                       job,
                                                       "");
Finally, we use bslmt_EntryPointFunctorAdapter_invoker to invoke the job in the context of a C-linkage function. Note that bslmt_EntryPointFunctorAdapter_invoker will deallocate the adapter object and the contained invokable job after executing it, so we must release the adapter from memory management via ManagedPtr. (In general, system APIs that register callbacks may fail; newly allocated adapters are loaded into ManagedPtr to aid in proper error and exception handling, outside the scope of this example.)
  executeWithArgument(bslmt_EntryPointFunctorAdapter_invoker,
                      threadData.ptr());
  threadData.release();
  assert(9 == result);

Function Documentation

void* bslmt_EntryPointFunctorAdapter_invoker ( void *  argument  ) 

Interpreting argument as an EntryPointFunctorAdapter_Base*, invoke argument->function(argument). Do not use outside this component.