# SoftBank Robotics documentation What's new in NAOqi 2.8?

# qi::Future groups

    #include <qi/futuregroup.hpp>

Provides helper containers for managing `qi::Future` objects lifetime.

## Summary

Global Classes

- class qi::ScopedFutureGroup

  Functions (class qi::ScopedFutureGroup)

  qi::ScopedFutureGroup::size

  qi::ScopedFutureGroup::~ScopedFutureGroup

  qi::ScopedFutureGroup::cancelAll

  qi::ScopedFutureGroup::empty

  qi::ScopedFutureGroup::add

## 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:
  1. have to wait until all tasks are finished;
  2. 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

`More...`

    #include <qi/futuregroup.hpp>

- Inherits: `noncopyable`, `qi::Trackable< ScopedFutureGroup >`

#### Public Functions

``~ScopedFutureGroup``()
template<class T>
void ``add``(Future<T> future)
void ``cancelAll``()
bool ``empty``() const
size_t ``size``() const

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

void `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.

void `qi::ScopedFutureGroup::``cancelAll`()

  Cancel all registered futures and unregister them.

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.

Glossary Site map Index Support Contact Legal Notices