From c3e2a7120f9e8336b87cb56224f2849c13b4ff0a Mon Sep 17 00:00:00 2001 From: Sara Golemon Date: Tue, 28 Jul 2015 16:41:16 -0700 Subject: [PATCH] Regenerate README.md from source Summary: Also fix URLs hand-modified by D2219135 which didn't quite update them enough. Point them at the new repo. Reviewed By: @yfeldblum Differential Revision: D2285053 --- folly/futures/README.md | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/folly/futures/README.md b/folly/futures/README.md index b2022e0c..b1cca16a 100644 --- a/folly/futures/README.md +++ b/folly/futures/README.md @@ -37,7 +37,11 @@ Although inspired by the C++11 std::future interface, it is not a drop-in replac Future chain made fulfilling Promise foo(42) -Promise fulfilled

Brief Guide

This brief guide covers the basics. For a more in-depth coverage skip to the appropriate section.

+Promise fulfilled + +

Blog Post #

+ +

In addition to this document, there is a blog post on code.facebook.com (June 2015).

Brief Guide

This brief guide covers the basics. For a more in-depth coverage skip to the appropriate section.

Let's begin with an example using an imaginary simplified Memcache client interface:

@@ -408,6 +412,8 @@ Although inspired by the C++11 std::future interface, it is not a drop-in replac

Future<T>::onError() allows you to have individual exception handlers as separate callbacks. The parameter you specify for your callback is exactly what onError() will try to catch. The callback will be passed over if the future doesn't contain that exception, otherwise, it will be executed and the T or Future<T> that it returns will become the resultant Future instead.

+
WARNING: Chaining together multiple calls to onError will NOT necessarily behave in the same way as multiple catch {} blocks after a try. Namely, if you throw an exception in one call to onError, the next onError will catch it.
+
intGeneratorThatMaybeThrows() // returns Future<int>
   // This is a good opportunity to use the plain value (no Try)
   // variant of then()
@@ -500,7 +506,7 @@ Although inspired by the C++11 std::future interface, it is not a drop-in replac
 
 
Future<int> f1 = ...;
 Future<string> f2 = ...;
-collectAll(f1, f2).then([](const std::tuple<Try<int>, Try<string>>& t){
+collectAll(f1, f2).then([](const std::tuple<Try<int>, Try<string>>& tup) {
   int i = std::get<0>(tup).value();
   string s = std::get<1>(tup).value();
   // ...
@@ -510,7 +516,7 @@ Although inspired by the C++11 std::future interface, it is not a drop-in replac
 
 

collect() is similar to collectAll(), but will terminate early if an exception is raised by any of the input Futures. Therefore, the returned Future is of type std::vector<T>. Like collectAll(), input Futures are moved in and are no longer valid, and the resulting Future's vector will contain the results of each input Future in the same order they were passed in (if all are successful). For instance:

-
collect(fs).then([](const std::vector<T>& vals){
+
collect(fs).then([](const std::vector<T>& vals) {
   for (const auto& val : vals) {
     // handle each response
   }
@@ -520,7 +526,7 @@ Although inspired by the C++11 std::future interface, it is not a drop-in replac
 });
 
 // Or using a Try:
-collect(fs).then([](const Try<std::vector<T>>& t){
+collect(fs).then([](const Try<std::vector<T>>& t) {
  // ...
 });
@@ -668,9 +674,9 @@ Although inspired by the C++11 std::future interface, it is not a drop-in replac

via() wouldn't be of much use without practical implementations around. We have a handful, and here's a (possibly incomplete) list.

    -
  • ThreadPoolExecutor is an abstract thread pool implementation that supports resizing, custom thread factories, pool and per-task stats, NUMA awareness, user-defined task expiration, and Codel task expiration. It and its subclasses are under active development. It currently has two implementations:
      -
    • CPUThreadPoolExecutor is a general purpose thread pool. In addition to the above features, it also supports task priorities.
    • -
    • IOThreadPoolExecutor is similar to CPUThreadPoolExecutor, but each thread spins on an EventBase (accessible to callbacks via EventBaseManager)
    • +
    • ThreadPoolExecutor is an abstract thread pool implementation that supports resizing, custom thread factories, pool and per-task stats, NUMA awareness, user-defined task expiration, and Codel task expiration. It and its subclasses are under active development. It currently has two implementations:
    • folly's EventBase is an Executor and executes work as a callback in the event loop
    • ManualExecutor only executes work when manually cranked. This is useful for testing.
    • @@ -678,7 +684,7 @@ Although inspired by the C++11 std::future interface, it is not a drop-in replac
    • QueuedImmediateExecutor is similar to InlineExecutor, but work added during callback execution will be queued instead of immediately executed
    • ScheduledExecutor is a subinterface of Executor that supports scheduled (i.e. delayed) execution. There aren't many implementations yet, see T5924392
    • Thrift's ThreadManager is an Executor but we aim to deprecate it in favor of the aforementioned CPUThreadPoolExecutor
    • -
    • FutureExecutor wraps another Executor and provides Future<T> addFuture(F func) which returns a Future representing the result of func. This is equivalent to futures::async(executor, func) and the latter should probably be preferred.
    • +
    • FutureExecutor wraps another Executor and provides Future<T> addFuture(F func) which returns a Future representing the result of func. This is equivalent to futures::async(executor, func) and the latter should probably be preferred.

Timeouts and related features

Futures provide a number of timing-related features. Here's an overview.

Timing implementation #

Timing resolution #

@@ -703,7 +709,7 @@ Although inspired by the C++11 std::future interface, it is not a drop-in replac f = foo().within(milliseconds(500)); // Same deal, but a timeout will trigger the provided exception instead -f2 = foo().within(millseconds(500), std::runtime_error("you took too long!")); +f2 = foo().within(milliseconds(500), std::runtime_error("you took too long!"));

onTimeout() #

@@ -1070,4 +1076,4 @@ The three laws refer to a different formulation of the axioms, in terms of the K

The tradeoff is memory. Each continuation has a stack, and that stack is usually fixed-size and has to be big enough to support whatever ordinary computation you might want to do on it. So each living continuation requires a relatively large amount of memory. If you know the number of continuations will be small, this might be a good fit. In particular, it might be faster, the code might read cleaner, and debugging stack traces might be much easier.

-

Futures takes the middle road between callback hell and continuations, one which has been trodden and proved useful in other languages. It doesn't claim to be the best model for all situations. Use your tools wisely.

+

Futures takes the middle road between callback hell and continuations, one which has been trodden and proved useful in other languages. It doesn't claim to be the best model for all situations. Use your tools wisely.

\ No newline at end of file -- 2.34.1