coral
A C++ library for distributed co-simulation
Public Member Functions | List of all members
coral::async::CommThread< StackData > Class Template Reference

Creates and controls a background communications thread. More...

#include "coral/async.hpp"

Public Member Functions

 CommThread ()
 Creates the background thread. More...
 
 ~CommThread () CORAL_NOEXCEPT
 If the CommThread object is still active, shuts down the background thread and waits for it to terminate. More...
 
 CommThread (CommThread &&other) CORAL_NOEXCEPT
 Move constructor. More...
 
CommThreadoperator= (CommThread &&other) CORAL_NOEXCEPT
 Move assignment operator. More...
 
template<typename Result >
std::future< Result > Execute (typename CommThreadTask< StackData, Result >::Type task)
 Executes a task asynchronously in the background thread. More...
 
void Shutdown ()
 Terminates the background thread in a controlled manner. More...
 
bool Active () const CORAL_NOEXCEPT
 Returns whether the CommThread object is active. More...
 

Detailed Description

template<typename StackData>
class coral::async::CommThread< StackData >

Creates and controls a background communications thread.

The constructor of this class creates a new thread whose lifetime is tied to that of the constructed object (i.e., the destructor will wait for the background thread to complete before returning.) This thread can be used to execute arbitrary code, but its primary design purpose is to run event-based communications code based on coral::net::Reactor. The thread therefore has a dedicated Reactor object, a reference to which is passed to all functions that are executed in it.

To execute tasks in the background thread, use the Execute() method. Results and exceptions from such functions should be transferred to the foreground thread using the std::future / std::promise mechanism.

The background thread may have a dedicated object of type StackData. This is located on that thread's stack, and can be used to hold objects persistently across Execute() calls. The StackData object does not move in memory, and its lifetime ends before that of the Reactor. A reference to this object is passed to each function that is executed in the background thread. StackData may be void, in which case no object is ever created, and no reference is passed to the executed functions.

Any exceptions that are thrown in the background thread (as opposed to being reported using a promise) will cause the thread to terminate. This is true both for exceptions that escape functions which are executed with Execute() and for those thrown in code which is executed indirectly as a result of reactor events. If this happens, a subsequent call to Execute() or Shutdown() will throw a CommThreadDead exception. The original exception can be obtained from this object.

After construction, the CommThread object is in the "active" state, where Active() returns true. It remains in this state until one of the following happens, after which it is "inactive" and Active() returns false:

Template Parameters
StackDataThe type used for an object that holds stack data persistently across function calls in the background thread, or void if no such object is needed.

Constructor & Destructor Documentation

template<typename StackData >
coral::async::CommThread< StackData >::CommThread ( )
explicit

Creates the background thread.

Postcondition
Active() == true
template<typename StackData >
coral::async::CommThread< StackData >::~CommThread ( )

If the CommThread object is still active, shuts down the background thread and waits for it to terminate.

The destructor calls Shutdown() to terminate the thread, but it will silently ignore any exceptions thrown by that function. Therefore, it is usually recommended to call Shutdown() manually before destruction, in order to catch any errors that might have occurred in the background thread.

template<typename StackData >
coral::async::CommThread< StackData >::CommThread ( CommThread< StackData > &&  other)

Move constructor.

Postcondition
other.Active() == false

Member Function Documentation

template<typename StackData >
bool coral::async::CommThread< StackData >::Active ( ) const

Returns whether the CommThread object is active.

If this function returns false, there is no background thread associated with this object. It may have been terminated, or ownership of it may have been transferred to another CommThread object by a move operation.

The converse is not necessarily true, however: Even if Active() returns true, the thread may still have terminated due to an exception. The only way to discover whether this is the case is to attempt to run Execute() or Shutdown() and see if CommThreadDead is thrown. If this happens, Active() will return false afterwards.

template<typename StackData >
template<typename Result >
std::future< Result > coral::async::CommThread< StackData >::Execute ( typename CommThreadTask< StackData, Result >::Type  task)

Executes a task asynchronously in the background thread.

This function returns a std::future that shares its state with the std::promise object passed to the task function. The promise should be used to report results or errors. This may be done immediately, in the body of the task function, or it may be done at a later time by registering a reactor event.

A reference to the background thread's coral::net::Reactor object is also passed to task. Do not call coral::net::Reactor::Stop() on this object to terminate the thread; this will lead to unspecified behaviour. Instead, use Shutdown() to terminate the thread in a controlled manner.

Finally, if the type parameter StackData is not void, the function also receives a reference to an object of the given type. This object is located on the background thread's stack, and thus persists across function calls.

See CommThreadTask for more information about the type and signature of the task function.

Any exceptions that are thrown and allowed to escape from task will cause the background thread to terminate, and a subsequent call to Execute() or Shutdown() will throw a CommThreadDead exception, rendering the CommThread object in an inactive state.

Warning
Visual Studio versions prior to 2015 do not handle std::promise destruction correctly. Specifically, a destroyed std::promise does not cause a "broken promise" error to be thrown by its corresponding std::future. Thus, if an exception is thrown in the background thread when there are any unfulfilled promises, calls to std::future::get() will block indefinitely.
Template Parameters
ResultThe type of the function's "return value". The function will receive an object of type std::promise<Result> which it can use to return the value (or an exception). Result may be void, in which case the promise is simply used to report whether the task was completed successfully.
Parameters
[in]taskA function to be executed in the background thread.
Returns
A std::future object that shares state with the std::promise passed to the task function.
Exceptions
CommThreadDeadIf the background thread has terminated unexpectedly due to an exception.
Precondition
Active() == true
template<typename StackData >
CommThread< StackData > & coral::async::CommThread< StackData >::operator= ( CommThread< StackData > &&  other)

Move assignment operator.

Postcondition
other.Active() == false
template<typename StackData >
void coral::async::CommThread< StackData >::Shutdown ( )

Terminates the background thread in a controlled manner.

This function will block until the background thread has terminated. After it returns, the CommThread object will be in the "inactive" state.

Exceptions
CommThreadDeadIf the background thread has terminated unexpectedly due to an exception, either before this function was called or during the shutdown procedure. (The latter should usually not happen, as destructors are supposed to be noexcept.)
Precondition
Active() == true
Postcondition
Active() == false

The documentation for this class was generated from the following file: