qi::Future groups¶
#include <qi/futuregroup.hpp>
Provides helper containers for managing qi::Future
objects lifetime.
Summary¶
class qi::ScopedFutureGroup
Functions (class qi::ScopedFutureGroup)
Global Classes
Detailed Description¶
Rationale¶
class Service
{
// ...
public:
void add(Data data)
{
// No Future is ever canceled even if Service is destroyed!
qi::Future<PreparedData> ft = qi::async<PreparedData>(
boost::bind(&Service::prepare, this, data));
ft.andThenR<void>(boost::bind(&Service::process, this));
}
private:
PreparedData prepare(Data data);
void process(PreparedData& data);
// ...
};
// ...
class SomeApplication
{
// ...
public:
// ...
void run(std::vector<Data> alldata)
{
Service service;
while(!alldata.empty())
{
service.add(alldata.back()); // launches tasks
service.pop_back();
}
mainLoop(); // return on exit
// We cannot wait for service's tasks to end.
} // service is destroyed here but its tasks have not been canceled and might still be running!
};
In this example, once mainLoop()
call returns, if service
‘s tasks launched in add()
didn’t finish yet, they will try to acceed to a destroyed Service object.
- To fix this bug we either:
- have to wait until all tasks are finished;
- just cancel the tasks when we stop using the Service object.
qi::ScopedFutureGroup
helps fix the second case. This is apropriate for our example
because we want to cancel tasks only when the application is destroyed.
qi::ScopedFutureGroup¶
qi::ScopedFuture
can register futures which will be canceled if not already
finished when the qi::ScopedFutureGroup
is destroyed.
We can fix the example from the Rationale section by using it this way:
#include <qi/futuregroup.hpp>
class Service
{
// ...
qi::ScopedFutureGroup _runningTasks; // On destruction, cancel all registered futures still running.
public:
void add(Data data)
{
// Here we made sure to track the futures associated with this object.
_runningTasks.add(qi::async(boost::bind(&Service::prepare, this, data))
.andThenR<void>(boost::bind(&Service::process, this)));
}
// If we want to explicitely cancel all tasks running without destroying the Service object.
void cancel()
{
_runningTasks.cancelAll();
}
private:
PreparedData prepare(Data data);
void process(PreparedData& data);
// ...
};
In this case a Service
object will automatically cancel all tasks still running associated with
the futures registered using qi::ScopedFutureGroup::add
.
Also: The registered futures are never canceled if they have been finished first,
in which case qi::ScopedFutureGroup
will automatically stop tracking the future.
Reference¶
qi::ScopedFutureGroup Class Reference¶
Introduction¶
#include <qi/futuregroup.hpp>
- Inherits:
noncopyable
,qi::Trackable< ScopedFutureGroup >
Public Functions¶
-
()~ScopedFutureGroup
- template<class T>
-
void
(Future<T> future)add
-
void
()cancelAll
-
bool
() constempty
-
size_t
() constsize
Types¶
- typedef boost::container::flat_map< FutureUniqueId, boost::function< void()>> FutureCancelList¶
Detailed Description¶
Cancel a group of unfinished registered futures on destruction. Guarantees that the registered set of futures will be canceled whatever the reason of the destruction of the group. All public member functions are thread-safe unless specified.
Function Documentation¶
-
qi::ScopedFutureGroup::
~ScopedFutureGroup
()¶ Destructor, cancel all unfinished futures registered.
- template<class T>
-
Brief:
Parameters: - future -- Future to register.
qi::ScopedFutureGroup::
add
(Future<T> future)¶ Register a future to be canceled if not finished when this object is destroyed, or if cancelAll() is called. Futures finishing before cancelation will be automatically unregistered. Non-cancelable futures will be ignored.
-
bool
qi::ScopedFutureGroup::
empty
()const
¶ Brief:
Returns: True if there is no future registered, false otherwise.
-
size_t
qi::ScopedFutureGroup::
size
()const
¶ Brief:
Returns: Count of registered futures.