(wangle) s/continuation/callback
authorHans Fugal <fugalh@fb.com>
Thu, 26 Jun 2014 22:20:40 +0000 (15:20 -0700)
committerNicholas Ormrod <njormrod@fb.com>
Fri, 27 Jun 2014 22:06:39 +0000 (15:06 -0700)
Summary: The word "continuation" is too ambiguous. Prefer callback (except where we are actually talking about CSP continuations in the README).

Test Plan: Still builds. Nothing external is or should be calling `setContinuation`. But I'll wait for contbuild anyway.

Reviewed By: hannesr@fb.com

Subscribers: net-systems@, fugalh, exa

FB internal diff: D1406753

Tasks: 4480567

folly/wangle/Future-inl.h
folly/wangle/Future.h
folly/wangle/Later-inl.h
folly/wangle/Later.h
folly/wangle/README.md
folly/wangle/detail.h
folly/wangle/test/FutureTest.cpp

index 47bede0eaf7df5334f63649b03393cbebbf22ea0..cc6b6bf06f91ef0da00a71b92ea3fcd6e7080a5e 100644 (file)
@@ -45,7 +45,7 @@ Future<T>& Future<T>::operator=(Future<T>&& other) {
 template <class T>
 Future<T>::~Future() {
   if (obj_) {
-    setContinuation([](Try<T>&&) {}); // detach
+    setCallback_([](Try<T>&&) {}); // detach
   }
 }
 
@@ -57,9 +57,9 @@ void Future<T>::throwIfInvalid() const {
 
 template <class T>
 template <class F>
-void Future<T>::setContinuation(F&& func) {
+void Future<T>::setCallback_(F&& func) {
   throwIfInvalid();
-  obj_->setContinuation(std::move(func));
+  obj_->setCallback_(std::move(func));
   obj_ = nullptr;
 }
 
@@ -112,7 +112,7 @@ Future<T>::then(F&& func) {
      in some circumstances, but I think it should be explicit not implicit
      in the destruction of the Future used to create it.
      */
-  setContinuation(
+  setCallback_(
     [p, funcm](Try<T>&& t) mutable {
       p->fulfil([&]() {
           return (*funcm)(std::move(t));
@@ -139,12 +139,12 @@ Future<T>::then(F&& func) {
   // grab the Future now before we lose our handle on the Promise
   auto f = p->getFuture();
 
-  setContinuation(
+  setCallback_(
     [p, funcm](Try<T>&& t) mutable {
       try {
         auto f2 = (*funcm)(std::move(t));
         // that didn't throw, now we can steal p
-        f2.setContinuation([p](Try<B>&& b) mutable {
+        f2.setCallback_([p](Try<B>&& b) mutable {
             p->fulfilTry(std::move(b));
           });
       } catch (...) {
@@ -189,7 +189,7 @@ inline Future<T> Future<T>::via(Executor* executor) {
   folly::MoveWrapper<Promise<T>> p;
   auto f = p->getFuture();
 
-  setContinuation([executor, p](Try<T>&& t) mutable {
+  setCallback_([executor, p](Try<T>&& t) mutable {
       folly::MoveWrapper<Try<T>> tt(std::move(t));
       executor->add([p, tt]() mutable {
           p->fulfilTry(std::move(*tt));
@@ -320,7 +320,7 @@ whenAll(InputIterator first, InputIterator last)
 
   for (size_t i = 0; first != last; ++first, ++i) {
      auto& f = *first;
-     f.setContinuation([ctx, i](Try<T>&& t) {
+     f.setCallback_([ctx, i](Try<T>&& t) {
          ctx->results[i] = std::move(t);
          if (++ctx->count == ctx->total) {
            ctx->p.setValue(std::move(ctx->results));
@@ -347,7 +347,7 @@ whenAny(InputIterator first, InputIterator last) {
 
   for (size_t i = 0; first != last; first++, i++) {
     auto& f = *first;
-    f.setContinuation([i, ctx](Try<T>&& t) {
+    f.setCallback_([i, ctx](Try<T>&& t) {
       if (!ctx->done.exchange(true)) {
         ctx->p.setValue(std::make_pair(i, std::move(t)));
       }
index 5390705de0f3f28550e8e096cbff1a0e46ea6c32..b54b7c19f65e71fb60edfdcb7da84397fa32c9dd 100644 (file)
@@ -181,7 +181,7 @@ class Future {
   /// not worth listing all those and their fancy template signatures as
   /// friends. But it's not for public consumption.
   template <class F>
-  void setContinuation(F&& func);
+  void setCallback_(F&& func);
 
  private:
   typedef detail::FutureObject<T>* objPtr;
index 4f00e268f99e65ad93fe90d1f881cae249bd4f45..d1e1ef88c2e9239c0a6261f690a420c3249fabce 100644 (file)
@@ -134,7 +134,7 @@ Later<T> Later<T>::via(Executor* executor) {
   Later<T> later(std::move(starter_));
   later.future_ = promise->getFuture();
 
-  future_->setContinuation([executor, promise](Try<T>&& t) mutable {
+  future_->setCallback_([executor, promise](Try<T>&& t) mutable {
     folly::MoveWrapper<Try<T>> tt(std::move(t));
     executor->add([promise, tt]() mutable {
       promise->fulfilTry(std::move(*tt));
index 0f58ff3c848300dd4998c1549651ec2b764112bb..c37e698a61acab19190f569e03d89021db2f4657 100644 (file)
@@ -28,7 +28,7 @@ template <typename T> struct isLater;
 /*
  * Since wangle primitives (promise/future) are not thread safe, it is difficult
  * to build complex asynchronous workflows. A Later allows you to build such a
- * workflow before actually launching it so that continuations can be set in a
+ * workflow before actually launching it so that callbacks can be set in a
  * threadsafe manner.
  *
  * The interface to add additional work is the same as future: a then() method
index 4b793330e4826337168b8c8dd54ea5dbc03833c0..b97a7272559fbe72f650a366e3eec76458239676 100644 (file)
@@ -13,7 +13,7 @@ A framework for expressing asynchronous control flow in C++, that is composable
 
 Wangle is a futures-based async framework inspired by [Twitter's Finagle](http://twitter.github.io/finagle/) (which is in scala), and (loosely) building upon the existing (but anemic) Futures code found in the C++11 standard ([`std::future`](http://en.cppreference.com/w/cpp/thread/future)) and [`boost::future`](http://www.boost.org/doc/libs/1_53_0/boost/thread/future.hpp) (especially >= 1.53.0). Although inspired by the std::future interface, it is not syntactically drop-in compatible because some ideas didn't translate well enough and we decided to break from the API. But semantically, it should be straightforward to translate from existing std::future code to Wangle.
 
-The primary semantic differences are that Wangle Futures and Promises are not threadsafe; and as does `boost::future`, Wangle supports continuations (`then()`) and there are helper methods `whenAll()` and `whenAny()` which are important compositional building blocks.
+The primary semantic differences are that Wangle Futures and Promises are not threadsafe; and as does `boost::future`, Wangle supports continuing callbacks (`then()`) and there are helper methods `whenAll()` and `whenAny()` which are important compositional building blocks.
 
 ## Brief Synopsis
 
@@ -139,7 +139,7 @@ auto any = whenAny(futs.begin(), futs.end());
 
 `all` and `any` are Futures (for the exact type and usage see the header files).  They will be complete when all/one of `futs` are complete, respectively. (There is also `whenN()` for when you need *some*.)
 
-Second, we can attach continuations (aka callbacks) to a Future, and chain them together monadically. An example will clarify:
+Second, we can attach callbacks to a Future, and chain them together monadically. An example will clarify:
 
 ```C++
 Future<GetReply> fut1 = mc.get("foo");
@@ -163,7 +163,7 @@ Future<void> fut3 = fut2.then(
 
 That example is a little contrived but the idea is that you can transform a result from one type to another, potentially in a chain, and unhandled errors propagate. Of course, the intermediate variables are optional. `Try<T>` is the object wrapper that supports both value and exception.
 
-Using `then` to add continuations is idiomatic. It brings all the code into one place, which avoids callback hell.
+Using `then` to add callbacks is idiomatic. It brings all the code into one place, which avoids callback hell.
 
 Up to this point we have skirted around the matter of waiting for Futures. You may never need to wait for a Future, because your code is event-driven and all follow-up action happens in a then-block. But if want to have a batch workflow, where you initiate a batch of asynchronous operations and then wait for them all to finish at a synchronization point, then you will want to wait for a Future.
 
@@ -266,7 +266,7 @@ p.fulfil([]{
 ## FAQ
 
 ### Why not use std::future?
-No callback or continuation support.
+No callback support.
 See also http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3428.pdf
 
 ### Why not use boost::future?
@@ -278,7 +278,7 @@ See also http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3428.pdf
 C++. It boils down to wanting to return a Future by value for performance (move semantics and compiler optimizations), and programmer sanity, and needing a reference to the shared state by both the user (which holds the Future) and the asynchronous operation (which holds the Promise), and allowing either to go out of scope.
 
 ### What about proper continuations? Futures suck.
-People mean two things here, they either mean using continuations or they mean using generators which require continuations. It's important to know those are two distinct questions, but in our context the answer is the same because continuations are a prerequisite for generators.
+People mean two things here, they either mean using continuations (as in CSP) or they mean using generators which require continuations. It's important to know those are two distinct questions, but in our context the answer is the same because continuations are a prerequisite for generators.
 
 C++ doesn't directly support continuations very well. But there are some ways to do them in C/C++ that rely on some rather low-level facilities like `setjmp` and `longjmp` (among others). So yes, they are possible (cf. [Mordor](https://github.com/ccutrer/mordor)).
 
index 8a89c64139a8b02bcc15393ebfad96ae2bf35d19..105ebc3ae388c17d2150f73938bda772c1ff6a3a 100644 (file)
@@ -46,9 +46,9 @@ class FutureObject {
   }
 
   template <typename F>
-  void setContinuation(F func) {
+  void setCallback_(F func) {
     if (continuation_) {
-      throw std::logic_error("setContinuation called twice");
+      throw std::logic_error("setCallback_ called twice");
     }
 
     continuation_ = std::move(func);
@@ -111,7 +111,7 @@ struct VariadicContext {
 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.setContinuation([ctx](Try<typename THead::value_type>&& t) {
+  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));
@@ -123,7 +123,7 @@ whenAllVariadicHelper(VariadicContext<Ts...> *ctx, THead&& head, Fs&&... tail) {
 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.setContinuation([ctx](Try<typename THead::value_type>&& t) {
+  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));
index bc6f209b3a4844776aee943b228b05f964e8b8c5..df99aebb68d23dc071917e92fc06e4cec5ef6f03 100644 (file)
@@ -279,18 +279,18 @@ TEST(Future, finish) {
   Promise<int> p;
   auto f = p.getFuture().then([x](Try<int>&& t) { *x = t.value(); });
 
-  // The continuation hasn't executed
+  // The callback hasn't executed
   EXPECT_EQ(0, *x);
 
-  // The continuation has a reference to x
+  // The callback has a reference to x
   EXPECT_EQ(2, x.use_count());
 
   p.setValue(42);
 
-  // the continuation has executed
+  // the callback has executed
   EXPECT_EQ(42, *x);
 
-  // the continuation has been destructed
+  // the callback has been destructed
   // and has released its reference to x
   EXPECT_EQ(1, x.use_count());
 }
@@ -676,7 +676,7 @@ TEST(Future, waitWithSemaphore) {
   EXPECT_EQ(result.load(), 1);
   p.setValue(42);
   t.join();
-  // validate that the continuation ended up executing in this thread, which
+  // validate that the callback ended up executing in this thread, which
   // is more to ensure that this test actually tests what it should
   EXPECT_EQ(id, std::this_thread::get_id());
   EXPECT_EQ(result.load(), 42);