(wangle) s/State/Core/
authorHans Fugal <fugalh@fb.com>
Wed, 15 Oct 2014 16:31:52 +0000 (09:31 -0700)
committerdcsommer <dcsommer@fb.com>
Fri, 17 Oct 2014 18:42:24 +0000 (11:42 -0700)
Summary:
codemod
`State` is such an overloaded term, and not really the best to describe this backing future/promise object. Yes, it holds the state but it's more than that and it gets in the way of calling the states of the state machines `State`s.

Test Plan: builds and tests pass

Reviewed By: davejwatson@fb.com

Subscribers: trunkagent, net-systems@, fugalh, exa, njormrod

FB internal diff: D1615707

folly/wangle/Future-inl.h
folly/wangle/Future.h
folly/wangle/Promise-inl.h
folly/wangle/Promise.h
folly/wangle/detail/Core.h [new file with mode: 0644]
folly/wangle/detail/State.h [deleted file]

index e66e504c0715cbb252f8e429f20ea76821dbde95..cf10e9f466a280c5b3d68a8992a4c97878ff75ec 100644 (file)
@@ -19,7 +19,7 @@
 #include <chrono>
 #include <thread>
 
-#include <folly/wangle/detail/State.h>
+#include <folly/wangle/detail/Core.h>
 #include <folly/Baton.h>
 
 namespace folly { namespace wangle {
@@ -35,13 +35,13 @@ struct isFuture<Future<T> > {
 };
 
 template <class T>
-Future<T>::Future(Future<T>&& other) noexcept : state_(nullptr) {
+Future<T>::Future(Future<T>&& other) noexcept : core_(nullptr) {
   *this = std::move(other);
 }
 
 template <class T>
 Future<T>& Future<T>::operator=(Future<T>&& other) {
-  std::swap(state_, other.state_);
+  std::swap(core_, other.core_);
   return *this;
 }
 
@@ -52,15 +52,15 @@ Future<T>::~Future() {
 
 template <class T>
 void Future<T>::detach() {
-  if (state_) {
-    state_->detachFuture();
-    state_ = nullptr;
+  if (core_) {
+    core_->detachFuture();
+    core_ = nullptr;
   }
 }
 
 template <class T>
 void Future<T>::throwIfInvalid() const {
-  if (!state_)
+  if (!core_)
     throw NoState();
 }
 
@@ -68,7 +68,7 @@ template <class T>
 template <class F>
 void Future<T>::setCallback_(F&& func) {
   throwIfInvalid();
-  state_->setCallback(std::move(func));
+  core_->setCallback(std::move(func));
 }
 
 template <class T>
@@ -95,10 +95,10 @@ Future<T>::then(F&& func) {
      sophisticated that avoids making a new Future object when it can, as an
      optimization. But this is correct.
 
-     state_ can't be moved, it is explicitly disallowed (as is copying). But
+     core_ can't be moved, it is explicitly disallowed (as is copying). But
      if there's ever a reason to allow it, this is one place that makes that
      assumption and would need to be fixed. We use a standard shared pointer
-     for state_ (by copying it in), which means in essence obj holds a shared
+     for core_ (by copying it in), which means in essence obj holds a shared
      pointer to itself.  But this shouldn't leak because Promise will not
      outlive the continuation, because Promise will setException() with a
      broken Promise if it is destructed before completed. We could use a
@@ -110,11 +110,11 @@ Future<T>::then(F&& func) {
      We have to move in the Promise and func using the MoveWrapper
      hack. (func could be copied but it's a big drag on perf).
 
-     Two subtle but important points about this design. detail::State has no
+     Two subtle but important points about this design. detail::Core has no
      back pointers to Future or Promise, so if Future or Promise get moved
      (and they will be moved in performant code) we don't have to do
      anything fancy. And because we store the continuation in the
-     detail::State, not in the Future, we can execute the continuation even
+     detail::Core, not in the Future, we can execute the continuation even
      after the Future has gone out of scope. This is an intentional design
      decision. It is likely we will want to be able to cancel a continuation
      in some circumstances, but I think it should be explicit not implicit
@@ -172,21 +172,21 @@ template <class T>
 typename std::add_lvalue_reference<T>::type Future<T>::value() {
   throwIfInvalid();
 
-  return state_->value();
+  return core_->value();
 }
 
 template <class T>
 typename std::add_lvalue_reference<const T>::type Future<T>::value() const {
   throwIfInvalid();
 
-  return state_->value();
+  return core_->value();
 }
 
 template <class T>
 Try<T>& Future<T>::getTry() {
   throwIfInvalid();
 
-  return state_->getTry();
+  return core_->getTry();
 }
 
 template <class T>
@@ -195,7 +195,7 @@ inline Future<T> Future<T>::via(Executor* executor) {
   throwIfInvalid();
 
   this->deactivate();
-  state_->setExecutor(executor);
+  core_->setExecutor(executor);
 
   return std::move(*this);
 }
@@ -203,7 +203,7 @@ inline Future<T> Future<T>::via(Executor* executor) {
 template <class T>
 bool Future<T>::isReady() const {
   throwIfInvalid();
-  return state_->ready();
+  return core_->ready();
 }
 
 // makeFuture
index df30efc5adb2acaa32d32d80bb062252c04d2128..3f46034bf0a02c59422bf47b339b8d531326e475 100644 (file)
@@ -199,23 +199,23 @@ class Future {
   ///
   /// Inactive Futures will activate upon destruction.
   void activate() {
-    state_->activate();
+    core_->activate();
   }
   void deactivate() {
-    state_->deactivate();
+    core_->deactivate();
   }
   bool isActive() {
-    return state_->isActive();
+    return core_->isActive();
   }
 
  private:
-  typedef detail::State<T>* statePtr;
+  typedef detail::Core<T>* corePtr;
 
-  // shared state object
-  statePtr state_;
+  // shared core state object
+  corePtr core_;
 
   explicit
-  Future(statePtr obj) : state_(obj) {}
+  Future(corePtr obj) : core_(obj) {}
 
   void detach();
 
index 04cc9a3f84ca62fb639d7cdeabe864312745a7dd..98993c7c81f792c93824a9d947f3f10a34f56a0e 100644 (file)
 #include <thread>
 
 #include <folly/wangle/WangleException.h>
-#include <folly/wangle/detail/State.h>
+#include <folly/wangle/detail/Core.h>
 
 namespace folly { namespace wangle {
 
 template <class T>
-Promise<T>::Promise() : retrieved_(false), state_(new detail::State<T>())
+Promise<T>::Promise() : retrieved_(false), core_(new detail::Core<T>())
 {}
 
 template <class T>
-Promise<T>::Promise(Promise<T>&& other) : state_(nullptr) {
+Promise<T>::Promise(Promise<T>&& other) : core_(nullptr) {
   *this = std::move(other);
 }
 
 template <class T>
 Promise<T>& Promise<T>::operator=(Promise<T>&& other) {
-  std::swap(state_, other.state_);
+  std::swap(core_, other.core_);
   std::swap(retrieved_, other.retrieved_);
   return *this;
 }
 
 template <class T>
 void Promise<T>::throwIfFulfilled() {
-  if (!state_)
+  if (!core_)
     throw NoState();
-  if (state_->ready())
+  if (core_->ready())
     throw PromiseAlreadySatisfied();
 }
 
@@ -61,11 +61,11 @@ Promise<T>::~Promise() {
 
 template <class T>
 void Promise<T>::detach() {
-  if (state_) {
+  if (core_) {
     if (!retrieved_)
-      state_->detachFuture();
-    state_->detachPromise();
-    state_ = nullptr;
+      core_->detachFuture();
+    core_->detachPromise();
+    core_ = nullptr;
   }
 }
 
@@ -73,7 +73,7 @@ template <class T>
 Future<T> Promise<T>::getFuture() {
   throwIfRetrieved();
   retrieved_ = true;
-  return Future<T>(state_);
+  return Future<T>(core_);
 }
 
 template <class T>
@@ -85,13 +85,13 @@ void Promise<T>::setException(E const& e) {
 template <class T>
 void Promise<T>::setException(std::exception_ptr const& e) {
   throwIfFulfilled();
-  state_->setException(e);
+  core_->setException(e);
 }
 
 template <class T>
 void Promise<T>::fulfilTry(Try<T>&& t) {
   throwIfFulfilled();
-  state_->fulfil(std::move(t));
+  core_->fulfil(std::move(t));
 }
 
 template <class T>
index e14350e37e4fb044c58063d18dee7fe1b041c75f..a4eb94b1f51a837694e1af90c8f4b05663a21848 100644 (file)
@@ -38,7 +38,7 @@ public:
   Promise(Promise<T>&&);
   Promise& operator=(Promise<T>&&);
 
-  /** Return a Future tied to the shared state. This can be called only
+  /** Return a Future tied to the shared core state. This can be called only
     once, thereafter Future already retrieved exception will be raised. */
   Future<T> getFuture();
 
@@ -76,13 +76,13 @@ public:
   void fulfil(F&& func);
 
 private:
-  typedef typename Future<T>::statePtr statePtr;
+  typedef typename Future<T>::corePtr corePtr;
 
   // Whether the Future has been retrieved (a one-time operation).
   bool retrieved_;
 
-  // shared state object
-  statePtr state_;
+  // shared core state object
+  corePtr core_;
 
   void throwIfFulfilled();
   void throwIfRetrieved();
diff --git a/folly/wangle/detail/Core.h b/folly/wangle/detail/Core.h
new file mode 100644 (file)
index 0000000..f237c61
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * Copyright 2014 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <atomic>
+#include <mutex>
+#include <stdexcept>
+#include <vector>
+
+#include <folly/Optional.h>
+
+#include <folly/wangle/Try.h>
+#include <folly/wangle/Promise.h>
+#include <folly/wangle/Future.h>
+#include <folly/wangle/Executor.h>
+
+namespace folly { namespace wangle { namespace detail {
+
+// As of GCC 4.8.1, the std::function in libstdc++ optimizes only for pointers
+// to functions, using a helper avoids a call to malloc.
+template<typename T>
+void empty_callback(Try<T>&&) { }
+
+/** The shared state object for Future and Promise. */
+template<typename T>
+class Core {
+ public:
+  // This must be heap-constructed. There's probably a way to enforce that in
+  // code but since this is just internal detail code and I don't know how
+  // off-hand, I'm punting.
+  Core() = default;
+  ~Core() {
+    assert(calledBack_);
+    assert(detached_ == 2);
+  }
+
+  // not copyable
+  Core(Core const&) = delete;
+  Core& operator=(Core const&) = delete;
+
+  // not movable (see comment in the implementation of Future::then)
+  Core(Core&&) noexcept = delete;
+  Core& operator=(Core&&) = delete;
+
+  Try<T>& getTry() {
+    return *value_;
+  }
+
+  template <typename F>
+  void setCallback(F func) {
+    {
+      std::lock_guard<decltype(mutex_)> lock(mutex_);
+
+      if (callback_) {
+        throw std::logic_error("setCallback called twice");
+      }
+
+      callback_ = std::move(func);
+    }
+
+    maybeCallback();
+  }
+
+  void fulfil(Try<T>&& t) {
+    {
+      std::lock_guard<decltype(mutex_)> lock(mutex_);
+
+      if (ready()) {
+        throw std::logic_error("fulfil called twice");
+      }
+
+      value_ = std::move(t);
+      assert(ready());
+    }
+
+    maybeCallback();
+  }
+
+  void setException(std::exception_ptr const& e) {
+    fulfil(Try<T>(e));
+  }
+
+  template <class E> void setException(E const& e) {
+    fulfil(Try<T>(std::make_exception_ptr<E>(e)));
+  }
+
+  bool ready() const {
+    return value_.hasValue();
+  }
+
+  typename std::add_lvalue_reference<T>::type value() {
+    if (ready()) {
+      return value_->value();
+    } else {
+      throw FutureNotReady();
+    }
+  }
+
+  // Called by a destructing Future
+  void detachFuture() {
+    if (!callback_) {
+      setCallback(empty_callback<T>);
+    }
+    activate();
+    detachOne();
+  }
+
+  // Called by a destructing Promise
+  void detachPromise() {
+    if (!ready()) {
+      setException(BrokenPromise());
+    }
+    detachOne();
+  }
+
+  void deactivate() {
+    std::lock_guard<decltype(mutex_)> lock(mutex_);
+    active_ = false;
+  }
+
+  void activate() {
+    {
+      std::lock_guard<decltype(mutex_)> lock(mutex_);
+      active_ = true;
+    }
+    maybeCallback();
+  }
+
+  bool isActive() { return active_; }
+
+  void setExecutor(Executor* x) {
+    std::lock_guard<decltype(mutex_)> lock(mutex_);
+    executor_ = x;
+  }
+
+ private:
+  void maybeCallback() {
+    std::unique_lock<decltype(mutex_)> lock(mutex_);
+    if (!calledBack_ &&
+        value_ && callback_ && isActive()) {
+      // TODO(5306911) we should probably try/catch here
+      if (executor_) {
+        MoveWrapper<folly::Optional<Try<T>>> val(std::move(value_));
+        MoveWrapper<std::function<void(Try<T>&&)>> cb(std::move(callback_));
+        executor_->add([cb, val]() mutable { (*cb)(std::move(**val)); });
+        calledBack_ = true;
+      } else {
+        calledBack_ = true;
+        lock.unlock();
+        callback_(std::move(*value_));
+      }
+    }
+  }
+
+  void detachOne() {
+    bool shouldDelete;
+    {
+      std::lock_guard<decltype(mutex_)> lock(mutex_);
+      detached_++;
+      assert(detached_ == 1 || detached_ == 2);
+      shouldDelete = (detached_ == 2);
+    }
+
+    if (shouldDelete) {
+      // we should have already executed the callback with the value
+      assert(calledBack_);
+      delete this;
+    }
+  }
+
+  folly::Optional<Try<T>> value_;
+  std::function<void(Try<T>&&)> callback_;
+  bool calledBack_ = false;
+  unsigned char detached_ = 0;
+  bool active_ = true;
+  Executor* executor_ = nullptr;
+
+  // this lock isn't meant to protect all accesses to members, only the ones
+  // that need to be threadsafe: the act of setting value_ and callback_, and
+  // seeing if they are set and whether we should then continue.
+  std::mutex mutex_;
+};
+
+template <typename... Ts>
+struct VariadicContext {
+  VariadicContext() : total(0), count(0) {}
+  Promise<std::tuple<Try<Ts>... > > p;
+  std::tuple<Try<Ts>... > results;
+  size_t total;
+  std::atomic<size_t> count;
+  typedef Future<std::tuple<Try<Ts>...>> type;
+};
+
+template <typename... Ts, typename THead, typename... Fs>
+typename std::enable_if<sizeof...(Fs) == 0, void>::type
+whenAllVariadicHelper(VariadicContext<Ts...> *ctx, THead&& head, Fs&&... tail) {
+  head.setCallback_([ctx](Try<typename THead::value_type>&& t) {
+    std::get<sizeof...(Ts) - sizeof...(Fs) - 1>(ctx->results) = std::move(t);
+    if (++ctx->count == ctx->total) {
+      ctx->p.setValue(std::move(ctx->results));
+      delete ctx;
+    }
+  });
+}
+
+template <typename... Ts, typename THead, typename... Fs>
+typename std::enable_if<sizeof...(Fs) != 0, void>::type
+whenAllVariadicHelper(VariadicContext<Ts...> *ctx, THead&& head, Fs&&... tail) {
+  head.setCallback_([ctx](Try<typename THead::value_type>&& t) {
+    std::get<sizeof...(Ts) - sizeof...(Fs) - 1>(ctx->results) = std::move(t);
+    if (++ctx->count == ctx->total) {
+      ctx->p.setValue(std::move(ctx->results));
+      delete ctx;
+    }
+  });
+  // template tail-recursion
+  whenAllVariadicHelper(ctx, std::forward<Fs>(tail)...);
+}
+
+template <typename T>
+struct WhenAllContext {
+  explicit WhenAllContext() : count(0), total(0) {}
+  Promise<std::vector<Try<T> > > p;
+  std::vector<Try<T> > results;
+  std::atomic<size_t> count;
+  size_t total;
+};
+
+template <typename T>
+struct WhenAnyContext {
+  explicit WhenAnyContext(size_t n) : done(false), ref_count(n) {};
+  Promise<std::pair<size_t, Try<T>>> p;
+  std::atomic<bool> done;
+  std::atomic<size_t> ref_count;
+  void decref() {
+    if (--ref_count == 0) {
+      delete this;
+    }
+  }
+};
+
+template <typename T>
+struct WhenAllLaterContext {
+  explicit WhenAllLaterContext() : count(0), total(0) {}
+  std::function<void(std::vector<Try<T>>&&)> fn;
+  std::vector<Try<T> > results;
+  std::atomic<size_t> count;
+  size_t total;
+};
+
+}}} // namespace
diff --git a/folly/wangle/detail/State.h b/folly/wangle/detail/State.h
deleted file mode 100644 (file)
index c06e223..0000000
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * Copyright 2014 Facebook, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <atomic>
-#include <mutex>
-#include <stdexcept>
-#include <vector>
-
-#include <folly/Optional.h>
-
-#include <folly/wangle/Try.h>
-#include <folly/wangle/Promise.h>
-#include <folly/wangle/Future.h>
-#include <folly/wangle/Executor.h>
-
-namespace folly { namespace wangle { namespace detail {
-
-// As of GCC 4.8.1, the std::function in libstdc++ optimizes only for pointers
-// to functions, using a helper avoids a call to malloc.
-template<typename T>
-void empty_callback(Try<T>&&) { }
-
-/** The shared state object for Future and Promise. */
-template<typename T>
-class State {
- public:
-  // This must be heap-constructed. There's probably a way to enforce that in
-  // code but since this is just internal detail code and I don't know how
-  // off-hand, I'm punting.
-  State() = default;
-  ~State() {
-    assert(calledBack_);
-    assert(detached_ == 2);
-  }
-
-  // not copyable
-  State(State const&) = delete;
-  State& operator=(State const&) = delete;
-
-  // not movable (see comment in the implementation of Future::then)
-  State(State&&) noexcept = delete;
-  State& operator=(State&&) = delete;
-
-  Try<T>& getTry() {
-    return *value_;
-  }
-
-  template <typename F>
-  void setCallback(F func) {
-    {
-      std::lock_guard<decltype(mutex_)> lock(mutex_);
-
-      if (callback_) {
-        throw std::logic_error("setCallback called twice");
-      }
-
-      callback_ = std::move(func);
-    }
-
-    maybeCallback();
-  }
-
-  void fulfil(Try<T>&& t) {
-    {
-      std::lock_guard<decltype(mutex_)> lock(mutex_);
-
-      if (ready()) {
-        throw std::logic_error("fulfil called twice");
-      }
-
-      value_ = std::move(t);
-      assert(ready());
-    }
-
-    maybeCallback();
-  }
-
-  void setException(std::exception_ptr const& e) {
-    fulfil(Try<T>(e));
-  }
-
-  template <class E> void setException(E const& e) {
-    fulfil(Try<T>(std::make_exception_ptr<E>(e)));
-  }
-
-  bool ready() const {
-    return value_.hasValue();
-  }
-
-  typename std::add_lvalue_reference<T>::type value() {
-    if (ready()) {
-      return value_->value();
-    } else {
-      throw FutureNotReady();
-    }
-  }
-
-  // Called by a destructing Future
-  void detachFuture() {
-    if (!callback_) {
-      setCallback(empty_callback<T>);
-    }
-    activate();
-    detachOne();
-  }
-
-  // Called by a destructing Promise
-  void detachPromise() {
-    if (!ready()) {
-      setException(BrokenPromise());
-    }
-    detachOne();
-  }
-
-  void deactivate() {
-    std::lock_guard<decltype(mutex_)> lock(mutex_);
-    active_ = false;
-  }
-
-  void activate() {
-    {
-      std::lock_guard<decltype(mutex_)> lock(mutex_);
-      active_ = true;
-    }
-    maybeCallback();
-  }
-
-  bool isActive() { return active_; }
-
-  void setExecutor(Executor* x) {
-    std::lock_guard<decltype(mutex_)> lock(mutex_);
-    executor_ = x;
-  }
-
- private:
-  void maybeCallback() {
-    std::unique_lock<decltype(mutex_)> lock(mutex_);
-    if (!calledBack_ &&
-        value_ && callback_ && isActive()) {
-      // TODO(5306911) we should probably try/catch here
-      if (executor_) {
-        MoveWrapper<folly::Optional<Try<T>>> val(std::move(value_));
-        MoveWrapper<std::function<void(Try<T>&&)>> cb(std::move(callback_));
-        executor_->add([cb, val]() mutable { (*cb)(std::move(**val)); });
-        calledBack_ = true;
-      } else {
-        calledBack_ = true;
-        lock.unlock();
-        callback_(std::move(*value_));
-      }
-    }
-  }
-
-  void detachOne() {
-    bool shouldDelete;
-    {
-      std::lock_guard<decltype(mutex_)> lock(mutex_);
-      detached_++;
-      assert(detached_ == 1 || detached_ == 2);
-      shouldDelete = (detached_ == 2);
-    }
-
-    if (shouldDelete) {
-      // we should have already executed the callback with the value
-      assert(calledBack_);
-      delete this;
-    }
-  }
-
-  folly::Optional<Try<T>> value_;
-  std::function<void(Try<T>&&)> callback_;
-  bool calledBack_ = false;
-  unsigned char detached_ = 0;
-  bool active_ = true;
-  Executor* executor_ = nullptr;
-
-  // this lock isn't meant to protect all accesses to members, only the ones
-  // that need to be threadsafe: the act of setting value_ and callback_, and
-  // seeing if they are set and whether we should then continue.
-  std::mutex mutex_;
-};
-
-template <typename... Ts>
-struct VariadicContext {
-  VariadicContext() : total(0), count(0) {}
-  Promise<std::tuple<Try<Ts>... > > p;
-  std::tuple<Try<Ts>... > results;
-  size_t total;
-  std::atomic<size_t> count;
-  typedef Future<std::tuple<Try<Ts>...>> type;
-};
-
-template <typename... Ts, typename THead, typename... Fs>
-typename std::enable_if<sizeof...(Fs) == 0, void>::type
-whenAllVariadicHelper(VariadicContext<Ts...> *ctx, THead&& head, Fs&&... tail) {
-  head.setCallback_([ctx](Try<typename THead::value_type>&& t) {
-    std::get<sizeof...(Ts) - sizeof...(Fs) - 1>(ctx->results) = std::move(t);
-    if (++ctx->count == ctx->total) {
-      ctx->p.setValue(std::move(ctx->results));
-      delete ctx;
-    }
-  });
-}
-
-template <typename... Ts, typename THead, typename... Fs>
-typename std::enable_if<sizeof...(Fs) != 0, void>::type
-whenAllVariadicHelper(VariadicContext<Ts...> *ctx, THead&& head, Fs&&... tail) {
-  head.setCallback_([ctx](Try<typename THead::value_type>&& t) {
-    std::get<sizeof...(Ts) - sizeof...(Fs) - 1>(ctx->results) = std::move(t);
-    if (++ctx->count == ctx->total) {
-      ctx->p.setValue(std::move(ctx->results));
-      delete ctx;
-    }
-  });
-  // template tail-recursion
-  whenAllVariadicHelper(ctx, std::forward<Fs>(tail)...);
-}
-
-template <typename T>
-struct WhenAllContext {
-  explicit WhenAllContext() : count(0), total(0) {}
-  Promise<std::vector<Try<T> > > p;
-  std::vector<Try<T> > results;
-  std::atomic<size_t> count;
-  size_t total;
-};
-
-template <typename T>
-struct WhenAnyContext {
-  explicit WhenAnyContext(size_t n) : done(false), ref_count(n) {};
-  Promise<std::pair<size_t, Try<T>>> p;
-  std::atomic<bool> done;
-  std::atomic<size_t> ref_count;
-  void decref() {
-    if (--ref_count == 0) {
-      delete this;
-    }
-  }
-};
-
-template <typename T>
-struct WhenAllLaterContext {
-  explicit WhenAllLaterContext() : count(0), total(0) {}
-  std::function<void(std::vector<Try<T>>&&)> fn;
-  std::vector<Try<T> > results;
-  std::atomic<size_t> count;
-  size_t total;
-};
-
-}}} // namespace