async_patterns::PendingCall

#include <pending_call.h>

This type is usually returned from a |DispatcherBound::AsyncCall| or calling |Callback|.

Summary

Let |Call| be a callable that takes zero arguments and returns |ReturnType|. |PendingCall| represents a call that is yet to be run, and offers a variety of ways to monitor its return value:

  • The caller may discard the |PendingCall|, at which point the call will be submitted for execution but its return value will be ignored.
  • The caller may call promise() to get a fpromise::promise that will resolve if the call runs to completion, or be abandoned if the call is dropped.
  • The caller may call Then to specify an async_patterns::Callback that will be called when the call runs to completion.

Constructors and Destructors

PendingCall(Call call, Submit submit, internal::Tag< ReturnType >)
PendingCall(const PendingCall &)
PendingCall(PendingCall &&)
~PendingCall()
Make the call if not already, and ignore the result.

Public functions

Then(async_patterns::Callback< void(R)> on_result)&&
void
Arranges |on_result| to be called with the result of the async call.
operator=(const PendingCall &)=delete
operator=(PendingCall &&) noexcept=delete
promise()&&
fpromise::promise< ReturnType >
Make the call and return a promise representing the return value of the call.

Protected functions

CallWithContinuation(Continuation continuation)
void

Public functions

PendingCall

 PendingCall(
  Call call,
  Submit submit,
  internal::Tag< ReturnType >
)

PendingCall

 PendingCall(
  const PendingCall &
)=delete

PendingCall

 PendingCall(
  PendingCall &&
) noexcept=delete

Then

void Then(
  async_patterns::Callback< void(R)> on_result
)&&

Arranges |on_result| to be called with the result of the async call.

|on_result| is an |async_patterns::Callback|. |R| could be identical to |ReturnType| or be some other compatible type such as |const ReturnType&|. Typically, the owner will declare a |Receiver| to mint these callbacks.

This allows two thread-unsafe objects living on different dispatchers to exchange messages in a ping-pong fashion. Example:

class Owner {
 public:
  Owner(async_dispatcher_t* owner_dispatcher)
    : receiver_{this, owner_dispatcher},
      background_loop_(&kAsyncLoopConfigNoAttachToCurrentThread),
      background_{background_loop_.dispatcher(), std::in_place} {}

  void StartDoingStuff() {
    // Make a call on |Background|, and then receive the result
    // at |DoneDoingStuff|.
    background_.AsyncCall(&Background::DoStuff, 42)
        .Then(receiver_.Once(&Owner::DoneDoingStuff));
  }

  void DoneDoingStuff(std::string result) {
    // Check the result from |Background::DoStuff|.
  }

 private:
  async_patterns::Receiver receiver_;
  async::Loop background_loop_;
  async_patterns::DispatcherBound background_;
};

See more in |async_patterns::DispatcherBound|.

operator=

PendingCall & operator=(
  const PendingCall &
)=delete

operator=

PendingCall & operator=(
  PendingCall &&
) noexcept=delete

promise

fpromise::promise< ReturnType > promise()&&

Make the call and return a promise representing the return value of the call.

The promise will resolve if the call runs to completion.

The promise will be abandoned if the call is dropped, such as if the target object that is supposed to respond to this async call is already destroyed.

Example:

async_patterns::Callback callback = ...;
fpromise::promise promise = callback(42).promise();

// Now you can do something with the promise..
executor.schedule_task(
    promise.and_then([] (int& value) { ... }));

~PendingCall

 ~PendingCall()

Make the call if not already, and ignore the result.

This leads to "fire-and-forget" behavior:

async_patterns::DispatcherBound object;

// This returns a |PendingCall|. If we do nothing with the return
// value, that means making the call and we don't care about its result.
object.AsyncCall(&MyType::SomeMethod);

Protected functions

CallWithContinuation

void CallWithContinuation(
  Continuation continuation
)