Futures VS. Promises

What's the difference between a Future and a Promise?

According to this discussion, Promise has finally been called CompletableFuture for inclusion in Java 8, and its javadoc explains:

A Future that may be explicitly completed (setting its value and status), and may be used as a CompletionStage, supporting dependent functions and actions that trigger upon its completion.

An example is also given on the list:

f.then((s -> aStringFunction(s)).thenAsync(s -> ...);

Note that the final API is slightly different but allows similar asynchronous execution:

CompletableFuture<String> f = ...;
f.thenApply(this::modifyString).thenAccept(System.out::println);

Futures vs. Promises

Future and Promise are the two separate sides of an asynchronous operation.

std::promise is used by the "producer/writer" of the asynchronous operation.

std::future is used by the "consumer/reader" of the asynchronous operation.

The reason it is separated into these two separate "interfaces" is to hide the "write/set" functionality from the "consumer/reader".

auto promise = std::promise<std::string>();

auto producer = std::thread([&]
{
promise.set_value("Hello World");
});

auto future = promise.get_future();

auto consumer = std::thread([&]
{
std::cout << future.get();
});

producer.join();
consumer.join();

One (incomplete) way to implement std::async using std::promise could be:

template<typename F>
auto async(F&& func) -> std::future<decltype(func())>
{
typedef decltype(func()) result_type;

auto promise = std::promise<result_type>();
auto future = promise.get_future();

std::thread(std::bind([=](std::promise<result_type>& promise)
{
try
{
promise.set_value(func()); // Note: Will not work with std::promise<void>. Needs some meta-template programming which is out of scope for this question.
}
catch(...)
{
promise.set_exception(std::current_exception());
}
}, std::move(promise))).detach();

return std::move(future);
}

Using std::packaged_task which is a helper (i.e. it basically does what we were doing above) around std::promise you could do the following which is more complete and possibly faster:

template<typename F>
auto async(F&& func) -> std::future<decltype(func())>
{
auto task = std::packaged_task<decltype(func())()>(std::forward<F>(func));
auto future = task.get_future();

std::thread(std::move(task)).detach();

return std::move(future);
}

Note that this is slightly different from std::async where the returned std::future will when destructed actually block until the thread is finished.

What is the difference between future and promise in vertx?

Promise are for defining non-blocking operations, and it's future() method returns the Future associated with a promise, to get notified of the promise completion and retrieve its value. The Future interface is the result of an action that may, or may not, have occurred yet.

Does future in c++ corresponding to promise in javascript?

  1. Yes.
  2. std::future<T> stands for a future result of T, i.e. the object will at some point in the future hold a T. std::promise<T> is an object promising to provide a T at some point in the future.

Which language got the naming right is debatable.

How do Clojure futures and promises differ?

Answering in Clojure terms, here are some examples from Sean Devlin's screencast:

(def a-promise (promise))
(deliver a-promise :fred)

(def f (future (some-sexp)))
(deref f)

Note that in the promise you are explicitly delivering a value that you select in a later computation (:fred in this case). The future, on the other hand, is being consumed in the same place that it was created. The some-expr is presumably launched behind the scenes and calculated in tandem (eventually), but if it remains unevaluated by the time it is accessed the thread blocks until it is available.


edited to add

To help further distinguish between a promise and a future, note the following:

promise

  1. You create a promise. That promise object can now be passed to any thread.
  2. You continue with calculations. These can be very complicated calculations involving side-effects, downloading data, user input, database access, other promises -- whatever you like. The code will look very much like your mainline code in any program.
  3. When you're finished, you can deliver the results to that promise object.
  4. Any item that tries to deref your promise before you're finished with your calculation will block until you're done. Once you're done and you've delivered the promise, the promise won't block any longer.

future

  1. You create your future. Part of your future is an expression for calculation.
  2. The future may or may not execute concurrently. It could be assigned a thread, possibly from a pool. It could just wait and do nothing. From your perspective you cannot tell.
  3. At some point you (or another thread) derefs the future. If the calculation has already completed, you get the results of it. If it has not already completed, you block until it has. (Presumably if it hasn't started yet, derefing it means that it starts to execute, but this, too, is not guaranteed.)

While you could make the expression in the future as complicated as the code that follows the creation of a promise, it's doubtful that's desirable. This means that futures are really more suited to quick, background-able calculations while promises are really more suited to large, complicated execution paths. Too, promises seem, in terms of calculations available, a little more flexible and oriented toward the promise creator doing the work and another thread reaping the harvest. Futures are more oriented toward automatically starting a thread (without the ugly and error-prone overhead) and going on with other things until you -- the originating thread -- need the results.

Differences between Futures in Python3 and Promises in ES6

  1. In both Python and ES6, await/async are based on generators. Is it a correct to think Futures are the same as Promises?

Not Future, but Python's Task is roughly equivalent to Javascript's Promise. See more details below.


  1. I have seen the terms Task, Future and Coroutine used in the asyncio documentation. What are the differences between them?

They're quite different concepts. Mainly, Task consists of Future and Coroutine. Let's describe these primitives briefly (I am going to simplify lots of things to describe only main principles):

Future

Future is simply an abstraction of value that may be not computed yet and will be available eventually. It's a simple container that only does one thing - whenever the value is set, fire all registered callbacks.

If you want to obtain that value, you register a callback via add_done_callback() method.

But unlike in Promise, the actual computation is done externally - and that external code has to call set_result() method to resolve the future.

Coroutine

Coroutine is the object very similar to Generator.

A generator is typically iterated within for loop. It yields values and, starting from PEP342 acceptance, it receives values.

A coroutine is typically iterated within the event loop in depths of asyncio library. A coroutine yields Future instances. When you are iterating over a coroutine and it yields a future, you shall wait until this future is resolved. After that you shall send the value of future into the coroutine, then you receive another future, and so on.

An await expression is practically identical to yield from expression, so by awaiting other coroutine, you stop until that coroutine has all its futures resolved, and get coroutine's return value. The Future is one-tick iterable and its iterator returns actual Future - that roughly means that await future equals yield from future equals yield future.

Task

Task is Future which has been actually started to compute and is attached to event loop. So it's special kind of Future (class Task is derived from class Future), which is associated with some event loop, and it has some coroutine, which serves as Task executor.

Task is usually created by event loop object: you give a coroutine to the loop, it creates Task object and starts to iterate over that coroutine in manner described above. Once the coroutine is finished, Task's Future is resolved by coroutine's return value.

You see, the task is quite similar to JS Promise - it encapsulates background job and its result.

Coroutine Function and Async Function

Coroutine func is a factory of coroutines, like generator function to generators. Notice the difference between Python's coroutine function and Javascript's async function - JS async function, when called, creates a Promise and its internal generator immediately starts being iterated, while Python's coroutine does nothing, until Task is created upon it.


  1. Should I start writing Python code that always has an event loop running?

If you need any asyncio feature, then you should. As it turns out it's quite hard to mix synchronous and asynchronous code - your whole program had better be asynchronous (but you can launch synchronous code chunks in separate threads via asyncio threadpool API)

why we need both std::promise and std::future?

The problem that promise/future exist to solve is to shepherd a value from one thread to another. It may also transfer an exception instead.

So the source thread must have some object that it can talk to, in order to send the desired value to the other thread. Alright... who owns that object? If the source has a pointer to something that the destination thread owns, how does the source know if the destination thread has deleted the object? Maybe the destination thread no longer cares about the value; maybe something changed such that it decided to just drop your thread on the floor and forget about it.

That's entirely legitimate code in some cases.

So now the question becomes why the source doesn't own the promise and simply give the destination a pointer/reference to it? Well, there's a good reason for that: the promise is owned by the source thread. Once the source thread terminates, the promise will be destroyed. Thus leaving the destination thread with a reference to a destroyed promise.

Oops.

Therefore, the only viable solution is to have two full-fledged objects: one for the source and one for the destination. These objects share ownership of the value that gets transferred. Of course, that doesn't mean that they couldn't be the same type; you could have something like shared_ptr<promise> or somesuch. After all, promise/future must have some shared storage of some sort internally, correct?

However, consider the interface of promise/future as they currently stand.

promise is non-copyable. You can move it, but you can't copy it. future is also non-copyable, but a future can become a shared_future that is copyable. So you can have multiple destinations, but only one source.

promise can only set the value; it can't even get it back. future can only get the value; it cannot set it. Therefore, you have an asymmetric interface, which is entirely appropriate to this use case. You don't want the destination to be able to set the value and the source to be able to retrieve it. That's backwards code logic.

So that's why you want two objects. You have an asymmetric interface, and that's best handled with two related but separate types and objects.

Clarification needed about futures and promises in Scala

You can think of futures and promises as two different sides of a pipe.
On the promise side, data is pushed in, and on the future side, data can be pulled out.

And future is some sort of an asynchronous operation that would complete in a different execution path.

Actually, a future is a placeholder object for a value that may be become available at some point in time, asynchronously. It is not the asynchronous computation itself.

The fact that there is a future constructor called future that returns such a placeholder object and spawns an asynchronous computation that completes this placeholder object does not mean that the asynchronous computation is called a future. There are also other future constructors/factory methods.

But the point I do not get is how promise has a future?

To divide promises and futures into 2 separate interfaces was a design decision. You could have these two under the same interface Future, but that would then allow clients of futures to complete them instead of the intended completer of the future. This would cause unexpected errors, as there could be any number of contending completers.

E.g. for the asynchronous computation spawned by the future construct, it would no longer be clear whether it has to complete the promise, or if the client will do it.

Futures and promises are intended to constrain the flow of data in the program.
The idea is to have a future client that subscribes to the data to act on it once the data arrives.
The role of the promise client is to provide that data.
Mixing these two roles can lead to programs that are harder to understand or reason about.

You might also ask why the Promise trait does not extend Future. This is another design decision to discourage programmers from blindly passing Promises to clients where they should upcast the Promise to Future (this upcast is prone to be left out, whereas having to explicitly call future on the promise ensures you call it every time). In other words, by returning a promise you are giving the right to complete it to somebody else, and by returning the future you are giving the right to subscribe to it.

EDIT:

If you would like to learn more about futures, Chapter 4 in the Learning Concurrent Programming in Scala book describes them in detail. Disclaimer: I'm the author of the book.

Understanding Scala Futures and Promises

In your example you can consider equivalent p success { 10 } and Future(10). You will only need to extract the future from p to get the same result.

You may consider Promises as a writeable Future where you will define the success or failure of the computation. As it looks a bit imperative programming, you will probably use them in very particular cases. You can see some of those cases in this link.



Related Topics



Leave a reply



Submit