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

Functions

void * bslmt_EntryPointFunctorAdapter_invoker (void *argument)
 

Detailed Description

Outline

Purpose

Provide types and utilities to simplify thread creation.

Classes

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
// CREATORS
/// 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 bslstl::StringRef& message,
int *result,
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.
WordCountJob(const WordCountJob& original,
bslma::Allocator *basicAllocator = 0);
// MANIPULATORS
/// Count the number of words in the message and store the count in
/// the address specified on construction.
void operator()();
};
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);
}
}
}
#define BSLMF_NESTED_TRAIT_DECLARATION(t_TYPE, t_TRAIT)
Definition bslmf_nestedtraitdeclaration.h:231
Definition bslstl_string.h:1281
Definition bslma_allocator.h:457
Definition bslstl_stringref.h:372
Definition bslma_usesbslmaallocator.h:343

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);
job,
"");
Definition bslma_managedptr.h:1182
Definition bslmt_entrypointfunctoradapter.h:262
static void allocateAdapter(bslma::ManagedPtr< EntryPointFunctorAdapter< TYPE > > *adapter, const TYPE &invokable, const bslstl::StringRef &threadName, bslma::Allocator *basicAllocator=0)
Definition bslmt_entrypointfunctoradapter.h:395

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.)

threadData.ptr());
threadData.release();
assert(9 == result);
void * bslmt_EntryPointFunctorAdapter_invoker(void *argument)

Function Documentation

◆ bslmt_EntryPointFunctorAdapter_invoker()

void * bslmt_EntryPointFunctorAdapter_invoker ( void *  argument)

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