#ifndef __PROCESS_COLLECT_HPP__ #define __PROCESS_COLLECT_HPP__ #include #include #include #include #include #include #include #include #include namespace process { // Waits on each future in the specified set and returns the set of // resulting values. If any future is discarded then the result will // be a failure. Likewise, if any future fails than the result future // will be a failure. template Future > collect( std::list >& futures, const Option& timeout = None()); namespace internal { template class CollectProcess : public Process > { public: CollectProcess( const std::list >& _futures, const Option& _timeout, Promise >* _promise) : futures(_futures), timeout(_timeout), promise(_promise) {} virtual ~CollectProcess() { delete promise; } virtual void initialize() { // Stop this nonsense if nobody cares. promise->future().onDiscarded(defer(this, &CollectProcess::discarded)); // Only wait as long as requested. if (timeout.isSome()) { delay(timeout.get().remaining(), this, &CollectProcess::timedout); } typename std::list >::const_iterator iterator; for (iterator = futures.begin(); iterator != futures.end(); ++iterator) { (*iterator).onAny( defer(this, &CollectProcess::waited, std::tr1::placeholders::_1)); } } private: void discarded() { terminate(this); } void timedout() { // Need to discard all of the futures so any of their associated // resources can get properly cleaned up. typename std::list >::const_iterator iterator; for (iterator = futures.begin(); iterator != futures.end(); ++iterator) { Future future = *iterator; // Need a non-const copy to discard. future.discard(); } promise->fail("Collect failed: timed out"); terminate(this); } void waited(const Future& future) { if (future.isFailed()) { promise->fail("Collect failed: " + future.failure()); terminate(this); } else if (future.isDiscarded()) { promise->fail("Collect failed: future discarded"); terminate(this); } else { assert(future.isReady()); values.push_back(future.get()); if (futures.size() == values.size()) { promise->set(values); terminate(this); } } } const std::list > futures; const Option timeout; Promise >* promise; std::list values; }; } // namespace internal { template inline Future > collect( std::list >& futures, const Option& timeout) { Promise >* promise = new Promise >(); Future > future = promise->future(); spawn(new internal::CollectProcess(futures, timeout, promise), true); return future; } } // namespace process { #endif // __PROCESS_COLLECT_HPP__