iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
nrt::MessageCheckerResults< Msg > Class Template Reference

#include <nrt/Core/Blackboard/MessageCheckerResults.H>

template<class Msg>
class nrt::MessageCheckerResults< Msg >

Class that holds the results of MessageChecker<Checking>::check()

Modules that derive from MessageChecker can asynchronously query the Blackboard for any previously posted Message that matches the signature of the MessageChecker's Checking. A shared_ptr to an object of this class is returned by check(), see the declaration of the MessageChecker class. The MessageCheckerResults class is similar but not identical to MessageCheckerResults. It contains several std::future objects which hold future access to messages returned by check(). There is one key difference, which has to do with the fact that, legitimately, check() may or may not return any result, even if it is known that some poster exists that posts the desired message: that poster just may not have posted yet (this is different from the case, with MessageCheckerResults, where it is known that we have subscribers for a posting: then the callbacks for these subscribers will for sure be called). Because of this difference, we cannot know in advance how many results might be returned by a given call to check(). Initially, we guess that every Blackboard in the federation that has matching posters might return some results, so we we create one future for each of these Blackboards. We can wait on those, but some might actually receive nothing. Because we do not want to throw while waiting, it is not until we attempt to get() a result that we may discover that there is none. In this case an null shared_ptr to the result message will be returned (as opposed to throwing an exception, because this is not really an exceptional or error condition). The simplest example of this is: we issue a check() and one remote Blackboard has posters for the corresponding message; thus we create a future for that remote Blackboard, and the MessageCheckerResults are not empty nor exhausted(); we wait; the remote Blackboard had no message posted yet; we get(); there is no message to return; thus we return a null shared_ptr to message. This slightly complicates the way one may pull results out of MessageCheckerResults, as described in the doc of the member functions.

Canonical use example is as follows:

if (auto res = AsyncInputA::check())
{
// Looks like some poster(s) is/are connected to our AsyncInputA. They may or may not have posted anything yet,
// though. Check out the results. Note that get() may throw. get() may also return a null shared_ptr if no
// message has yet been posted (which is not an error):
while (res.exhausted() == false)
if (std::shared_ptr<MessageA const> msg = res.get())
{
// do something with msg
}
}

You can also handle exceptions, in the same way as for MessagePosterResults, except that the only exception you can get here is nrt::exception::BlackboardException.

Note that MessageCheckerResults is not inherently thread-safe, so in the unlikely event that you may have several threads consuming its results, you would have to ensure thread safety with an external mutex.

Alternatively to the above way of using results, you can also use an iterator-based syntax explained with the iterator definition below. See test-ResultsSyntax.C for examples.

Examples:
tests/test-Module.C.

Definition at line 99 of file MessageCheckerResults.H.

Public Member Functions

 MessageCheckerResults ()
 Default Constructor, contains no data.
 
 MessageCheckerResults (MessageCheckerResults< Msg > &&other)
 Constructor with move semantics.
 
 MessageCheckerResults (MessageCheckerResults< Msg > &other)=delete
 Forbid copy construction.
 
MessageCheckerResults< Msg > & operator= (MessageCheckerResults< Msg > &&other)
 Move Assignment operator.
 
MessageCheckerResults< Msg > & operator= (MessageCheckerResults< Msg > const &other)=delete
 Forbid copy-assignment.
 
 ~MessageCheckerResults ()
 Destructor. Will block and wait on any result that is still pending and then get() it, which may throw. More...
 
bool exhausted (std::chrono::microseconds const maxwait=std::chrono::microseconds(0))
 Is there possibly any more data coming from local and/or remote blackboards? More...
 
bool ready ()
 Is there one or more messages ready now, such that one call to get() would return it without any blocking?
 
 operator bool ()
 Returns true if we are not exhausted, i.e., we may have some results now or in the future.
 
bool waitall (std::chrono::microseconds const maxwait=std::chrono::hours::max())
 Wait for all results to be ready, up to a maximum total wait time. More...
 
std::shared_ptr< Msg const > get ()
 Get the next result. More...
 
iterator begin ()
 Get access to the first iterator. More...
 
iterator end ()
 Create an iterator that is equivalent to the 'end' of the sequence of futures.
 

Friends

class nrt::Blackboard
 
template<class Checking >
class nrt::MessageCheckerCore
 

Constructor & Destructor Documentation

template<class Msg >
nrt::MessageCheckerResults< Msg >::~MessageCheckerResults ( )
inline

Destructor. Will block and wait on any result that is still pending and then get() it, which may throw.

Yes this is a potentially throwing destructor, but that's ok as long as people don't derive from MessageCheckerResults (destructor is not virtual anyway). If you want to avoid waiting and possibly throwing here, just make sure that you waitall() and get() everything before your results run out of scope.

Definition at line 73 of file MessageCheckerResultsImpl.H.

Member Function Documentation

template<class Msg >
bool nrt::MessageCheckerResults< Msg >::exhausted ( std::chrono::microseconds const  maxwait = std::chrono::microseconds(0))
inline

Is there possibly any more data coming from local and/or remote blackboards?

We don't know for sure whether more data will be returned until we wait for it all, since we may have some pending queries to remote blackboards that may or may not return some result(s) in the future, depending on the contents of the remote Blackboard(s). So the only thing we can say for sure is when we have exhausted all data and no more will come, which is when we return true here. If we return false here, one can then check whether there is more data ready, using ready(). Here we first make a round over all possible pending results and see whether some are available immediately, in which case we return false. Otherwise, we make a second round in which we may wait up to a total of maxwait for any of the future results to come. If maxwait is 0, then we will not wait at all and only do the first round.

Definition at line 117 of file MessageCheckerResultsImpl.H.

Referenced by nrt::MessageCheckerResults< Msg >::begin().

template<class Msg >
bool nrt::MessageCheckerResults< Msg >::waitall ( std::chrono::microseconds const  maxwait = std::chrono::hours::max())
inline

Wait for all results to be ready, up to a maximum total wait time.

Returns true if all results are ready. If you just want to check for completion without blocking, just pass a zero maxwait duration.

Definition at line 151 of file MessageCheckerResultsImpl.H.

template<class Msg >
std::shared_ptr< Msg const > nrt::MessageCheckerResults< Msg >::get ( )
inline

Get the next result.

Get the next result, or an exception if some problem was encountered while fetching some result (e.g., dead remote blackboard). Note that this may block until the next result is ready, check ready() first and use waitall() or exhausted() to avoid waiting in get(). Beware that this returns a null shared_ptr if there was nothing left to get(); there is no way to avoid that for sure, since this is the only call that may throw (i.e., we might have a bunch of ready futures and exhausted() would return false, but if we discover here that none of them contained anything, then we will throw).

Definition at line 164 of file MessageCheckerResultsImpl.H.

template<class Msg >
nrt::MessageCheckerResults< Msg >::iterator nrt::MessageCheckerResults< Msg >::begin ( )

Get access to the first iterator.

Warning
You may only call begin() once on a MessageCheckerResults. Trying to call begin() multiple times will cause a std::range_error exception to be thrown.

Definition at line 223 of file MessageCheckerResultsImpl.H.

References nrt::MessageCheckerResults< Msg >::exhausted().


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