Boost logo

Boost :

From: Johan Torp (johan.torp_at_[hidden])
Date: 2008-05-16 06:47:04


After thinking more carefully on the problem I've realized it is
implementable using condition variables. Here is a revised proposal, which -
for now - excludes barriers.

---------------------------- Proposal ----------------------------

Add class future_expression that basically is a function which depend on
futures values.
- A typed evaluation function (some work) is associated with each future
dependency
--- This evaluation can result in that the future_expressions becomes ready
- A future dependency is a parent child relationship. This forms a graph
where "promise-futures" are leafs.
--- You can wait() on any future in the graph
- When a future is completed it tells it's parents they need to re-evaluate
via a future-complete callback
--- The future_expression that needs re-evaluation will:
--- 1. Schedule the associated evaluation to be run on the client thread on
next wait or is_ready is called
--- 2. Notifies it's condition in case the client thread was waiting on this
particular node
--- 3. Signals it's parents they too need to re-evaluate
------ This way, the notifications propagate upwards to the root future
------ Some future_expression might be scheduled for re-evaluation even
though
- When a future expression becomes ready it drops it's shared ownership to
all depending childs
--- They are no longer needed and can die
--- This is done as a part of the pending evaluations on the client thread
- For now this is not a concurrent object, neither are the futures formed
from it
--- All evaluation code can thus be single threaded
--- We can change this so that the work of evaluating a future is done by
the first thread waiting on it.
     
Note:
- The callback is ONLY usable by future_exprs. - No user code can be
executed by promise fulfilling code
- Other abstractions build on future_expressions rather than the dangerous
complete-callback

---------------------------- Part of interface
----------------------------

template<class T>
struct future_result
{
  T running_result_;
  bool value_is_final_;
  optional<exception> exception_;
  ...
};

/// A representation of a function which depends on futures.
///
template <class T>
class future_expression
{
  /// Default value if no dependencies are added
  future_expression(T starting_value);

  /// Add a future alongside with an evaluation function which will be
called lazily by waiting threads
  template<class U>
  void add_dependency<U> (shared_future<U> f,
                                      function<void(U future_value,
future_result<T>& result_setter)> on_ready);

  /// Perform pending evaluations. If none sets an exception or result wait
on the internal condition
  void wait();

  /// If not ready, perform pending evaluations. If none sets an exception
or result, return false
  bool is_ready();
};

---------------------------- Example code ----------------------------

void set_if_true(bool b, result& result_setter)
{
  if (b)
  {
    result_setter.running_value_ = true;
    result_setter.value_is_final_ = true;
  }
}

template<class T>
future<bool> operator||(future<bool> lhs, future<bool> rhs)
{
  future_expression<R> exp(false);
  exp.add_dependency(a1, &set_if_true);
  exp.add_dependency(a2, &set_if_true);
  return future<R>(exp);
}

template<class T>
void running_add(T value, result& result_setter)
{
  result_setter.running_value_ += value;
}

template<class T>
future<T> sum(vector<future<T>> futures)
{
  future_expression<T> exp(value_initialized<T>());

  for f in futures
     exp.add_dependency(f, &running_add);

  return future<T>(exp);
}

---------------------------- Conclusions ----------------------------
 
This mechanism would solve all the issues we've found. Most importantly it
allows making composite futures while prohibiting execution of user code
while fulfilling promises.

Unfortunately, I feel it might be a little cumbersome to use. Also, since we
need wait_for_many support it needs to get accepted alongside with the first
version of the future library. I was hoping this version could be very
lightweight.
 
What do you think? Any quick thoughts?

Johan

-- 
View this message in context: http://www.nabble.com/-future--Early-draft-of-wait-for-multiple-futures-interface-tp17242880p17272047.html
Sent from the Boost - Dev mailing list archive at Nabble.com.

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk