libAlgAudio  v1.99-440-g08538e5-dirty
The development library for AlgAudio framework.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
AlgAudio::LateReturn< Types > Class Template Reference

#include <LateReturn.hpp>

Public Member Functions

template<typename Ex >
const LateReturnCatch (std::function< void(std::shared_ptr< Exceptions::Exception >)> func) const
 
template<typename... X>
const LateReturnCatch (const Relay< X...> &r) const
 
template<typename Ex >
const LateReturnCatchAll (std::function< void(std::shared_ptr< Exceptions::Exception >)> func) const
 
 LateReturn (const Relay< Types...> &r)
 
 LateReturn (const LateReturn &other)=delete
 
 LateReturn (LateReturn &&other)
 
LateReturnoperator= (const LateReturn &other)=delete
 
LateReturnoperator= (LateReturn &&other)
 
const LateReturnThen (std::function< void(Types...)> f) const
 
const LateReturnThenReturn (Relay< Types...> r) const
 
const LateReturnThenSync (Sync &s) const
 

Friends

class Relay< Types...>
 

Detailed Description

template<typename... Types>
class AlgAudio::LateReturn< Types >

The LateReturn class template provides a global, universal mechanism for managing asynchronous code execution. The idea is that some functions may not be able to return their value immediatelly, but only after some longer time. Usually, such situation might be resolved by allowing the function to block execution, and simply call the function in another thread. Instead, a function can return a LateReturn<X>, which represents a value that is not yet available. The called can then use that returned LateReturn instance to define what action should be taken when that value arrives. A simple example of usage might be:

LateReturn<std::string> GetServerVersion(); // Uses TCP connection to request server version from a remote host.
...
void PrintServerInfo(){
GetServerVersion().Then([](std::string version){
std::cout << "Sever version is " << version << std::endl;
});
std::cout << "Requested version info from server, will report when it arrives..." << std::endl;
}
...

In the presented example, the code within lambda function is likely to be executed when PrintServerInfo() has already returned. However, if GetServerVersion has cached data, it may have the resulting value ready immediatelly, and in such case the lambda function will be called before the other text message is printed. The order in which continuation functions (the functions set with Then(), which represent action which should be called when the returned value is ready) are called may appear random and confusing, but the exact order should never be significant. What is guaranteed is that each continuation function is called as soon as both the latereturned value and the continuation function are set.

The lifetime of the stored function is kept to minumum. This is especially important when using lambdas to define continuations:

void function(){
Object x;
LateReturningFunc().Then([&x](){
x.value = 5;
});
}

In the above example, setting x.value may be an invalid operation, because the x Object may have been already destructed when the LateReturningFunc completes it's work.

One possible solution is to use shared pointers to prolong object lifetime as long as the stored function is needed. The stored function will be destructed just after it is called, and so will be the captured shared_ptr. However, it is possible to create ownership cycles, if such a shared pointer gets stored in a LateReturn that is owned by the same object.

Similarly, there is nothing wrong in capturing this by a lambda that is passed to Then(), just keep in mind what the LateReturn lifetime will be, and whether it is guaranteed that this will still exist by the time there continuation function is invoked.

The return value may never become ready, for example if the latereturning function keeps waiting for en event that never happens. In such case the continuation will never get called.

It is also possible that when LateReturning function has failed and cannot provide a value, it decides to thow an exception, to notify whoever called it about some kind of a problem. Obviously, using a try{}catch(){} block won't work, because at the time an exception occurs, the actual stack for the call to latereturning function no longer exists. Instead, you can use Catch() to set a handler for a given exception. Example:

GetServerVersion().Then([](std::string version){
std::cout << version << std::endl;
}).Catch<Exceptions::Communication>([](std::shared_ptr<Exceptions::Exception> ex){
std::cout << "Failed to get server version, reason: " << ex->reason << std::endl;
});

Similarly to continuations, exception handling functions are also called when appropriate, which may mean a long delay.

See Relay documentation for details on how to write a LateReturning function.

See also
Relay

Constructor & Destructor Documentation

template<typename... Types>
AlgAudio::LateReturn< Types >::LateReturn ( const Relay< Types...> &  r)
inline

Implicit converting constructor from a Relay.

template<typename... Types>
AlgAudio::LateReturn< Types >::LateReturn ( const LateReturn< Types > &  other)
delete
Warning
Deleted. No copy-constructing.
template<typename... Types>
AlgAudio::LateReturn< Types >::LateReturn ( LateReturn< Types > &&  other)
inline

Member Function Documentation

template<typename... Types>
template<typename Ex >
const LateReturn& AlgAudio::LateReturn< Types >::Catch ( std::function< void(std::shared_ptr< Exceptions::Exception >)>  func) const
inline

Sets the handler for a given type of exceptions.

Parameters
funcThe handler function to be called when selected exception happen.

Only one handler for each exception class may be set. Setting another overrides the previous.

template<typename... Types>
template<typename... X>
const LateReturn& AlgAudio::LateReturn< Types >::Catch ( const Relay< X...> &  r) const
inline

Tells a LateReturn to pass all latethrown exceptions to another Relay. Chaining relays this way enables correct logical stack unwinding.

Parameters
rThe parent Relay.
See also
Relay
template<typename... Types>
template<typename Ex >
const LateReturn& AlgAudio::LateReturn< Types >::CatchAll ( std::function< void(std::shared_ptr< Exceptions::Exception >)>  func) const
inline

Sets the default handler for all exceptions.

Parameters
funcThe handler function to be called when any exception happen, and there is no specific handler set for that type of exception.

Only one default handler may be set. Setting another overrides the previous.

template<typename... Types>
LateReturn& AlgAudio::LateReturn< Types >::operator= ( const LateReturn< Types > &  other)
delete
Warning
Deleted. No copy-assigning.
template<typename... Types>
LateReturn& AlgAudio::LateReturn< Types >::operator= ( LateReturn< Types > &&  other)
inline
template<typename... Types>
const LateReturn& AlgAudio::LateReturn< Types >::Then ( std::function< void(Types...)>  f) const
inline

This method is used define continuation action.

Parameters
fThe continuation function that should be called when latereturned value becomes available.
Warning
f may be called immediatelly, if the value is already available.

Only one continuation function may be set. Setting another overrides the previous.

template<typename... Types>
const LateReturn& AlgAudio::LateReturn< Types >::ThenReturn ( Relay< Types...>  r) const
inline

A helper method for returning another Relay's value when the result becomes ready.

Parameters
rThe Relay that should return then.
See also
Relay
template<typename... Types>
const LateReturn& AlgAudio::LateReturn< Types >::ThenSync ( Sync s) const
inline

A helper method for triggering a Sync when returned value is available.

Parameters
sThe Sync to trigger.
See also
Sync

Friends And Related Function Documentation

template<typename... Types>
friend class Relay< Types...>
friend

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