template <typename T>

class DispatcherBound

Defined at line 103 of file ../../sdk/lib/async_patterns/cpp/dispatcher_bound.h

|DispatcherBound

<T

>| enables an owner object living on some arbitrary thread,

to construct, call methods on, and destroy an object of type |T| that must be

used from a particular [synchronized async dispatcher][synchronized-dispatcher].

Thread-unsafe asynchronous types should be used from synchronized dispatchers

(e.g. a single-threaded async loop). Because the dispatcher may be running

code to manipulate such objects, one should not use the same objects from

other unrelated threads and cause data races.

However, it may not always be possible for an entire tree of objects to

live on the same async dispatcher, due to design or legacy constraints.

|DispatcherBound| helps one divide classes along dispatcher boundaries.

An example:

// |Background| always lives on a background dispatcher, provided

// at construction time.

class Background {

public:

explicit Background() {

// Perform some asynchronous work. The work is canceled if

// |Background| is destroyed.

task_.Post(async_get_default_dispatcher());

}

private:

void DoSomething();

// |task_| manages an async task that borrows the containing

// |Background| object and is not thread safe. It must be destroyed

// on the dispatcher to ensure that task cancellation is not racy.

async::TaskClosureMethod

<Background

,

&Background

::DoSomething> task_{this};

};

class Owner {

public:

// Asynchronously constructs a |Background| object on its dispatcher.

// Code in |Owner| and code in |Background| may run concurrently.

//

// The dispatcher will not be attached to the current thread, but will

// be attached to the loop thread. This way, the |Background| object

// can obtain a dispatcher from its constructor using

// |async_get_default_dispatcher|.

explicit Owner() :

background_loop_(

&kAsyncLoopConfigNoAttachToCurrentThread

),

background_{background_loop_.dispatcher(), std::in_place} {}

private:

// The async loop which will manage |Background| objects.

// This will always be paired with a |DispatcherBound| object.

async::Loop background_loop_;

// The |DispatcherBound| which manages |Background| on its loop.

// During destruction, |background_| will schedule the asynchronous

// destruction of the wrapped |Background| object on the dispatcher.

async_patterns::DispatcherBound

<Background

> background_;

};

|DispatcherBound| itself is thread-compatible.

## Safety of sending arguments

When constructing |T| and calling member functions of |T|, it is possible to

pass additional arguments if the constructor or member function requires it.

The argument will be forwarded from the caller's thread into a heap data

structure, and later moved into the thread which would run the dispatcher

task asynchronously. Each argument must be safe to send to a different

thread. See |async_patterns::BindForSending| for the detailed requirements.

[synchronized-dispatcher]:

https://fuchsia.dev/fuchsia-src/development/languages/c-cpp/thread-safe-async#synchronized-dispatcher

Public Methods

template <typename... Args>
void DispatcherBound<T> (async_dispatcher_t * dispatcher, std::in_place_t , Args &&... args)

Asynchronously constructs |T| on a task posted to |dispatcher|.

Arguments after |std::in_place| are sent to the constructor of |T|.

See |async_patterns::BindForSending| for detailed requirements on |args|.

If you'd like to pass a |dispatcher| to |T| as a constructor argument,

see |async_patterns::PassDispatcher|.

If the dispatcher is shutdown, |T| will be synchronously constructed.

Defined at line 115 of file ../../sdk/lib/async_patterns/cpp/dispatcher_bound.h

void DispatcherBound<T> (async_dispatcher_t * dispatcher)

Constructs a |DispatcherBound| that does not hold an instance of |T|.

One may later construct |T| using |emplace| on the |dispatcher|.

Defined at line 123 of file ../../sdk/lib/async_patterns/cpp/dispatcher_bound.h

template <typename T2 = T, typename... Args>
void emplace (Args &&... args)

Asynchronously constructs |T| on a task posted to the dispatcher.

If this object already holds an instance of |T|, that older instance will

be asynchronously destroyed on the dispatcher.

If |T2| is specified, it must be same as |T| or a subclass. Then an instance

of |T2| will be constructed. This can be useful for mocking: |T| may be some

interface, and when constructing the object, either a fake (in unit tests)

or a real concrete type (in production) will be specified.

If you'd like to pass a |dispatcher| to |T| as a constructor argument,

see |async_patterns::PassDispatcher|.

See |async_patterns::BindForSending| for detailed requirements on |args|.

Defined at line 140 of file ../../sdk/lib/async_patterns/cpp/dispatcher_bound.h

template <typename Member, typename... Args>
auto AsyncCall (Member T::* member, Args &&... args)

Asynchronously calls |member|, a pointer to member function of |T|, using

the provided |args|.

|AsyncCall| returns a |PendingCall| object that lets you asynchronously

monitor the result. You may either:

- Make a fire-and-forget call, by discarding the returned object, or

- Get a promise carrying the return value of the function by calling

`promise()` on the object, yielding a |fpromise::promise

<ReturnType

>|, or

- Call `Then()` on the object and pass a |Callback

<void

(ReturnType)>|.

See |PendingCall| for details.

In particular, if |member| returns void, you could attach promises/callbacks

that take void to asynchronously get notified when |member| has finished execution.

Example:

class Owner {

public:

Owner(async_dispatcher_t* owner_dispatcher) : receiver_{this, owner_dispatcher} {

background_.emplace();

// Tell |background_| to |DoSomething|, then send back the return

// value to |Owner| using |receiver_|.

background_

.AsyncCall(

&Background

::DoSomething)

.Then(receiver_.Once(

&Owner

::DoneSomething));

}

void DoneSomething(Result result) {

// |Background::DoSomething| has completed with |result|...

}

private:

async::Loop background_loop_;

async_patterns::DispatcherBound

<Background

> background_{background_loop_.dispatcher()};

async_patterns::Receiver

<Owner

> receiver_;

};

See |async_patterns::BindForSending| for detailed requirements on |args|.

If |Background::DoSomething| is an overloaded member function, you may

disambiguate it by spelling out its signature:

background_.AsyncCall

<void

(Result)>(

&Background

::DoSomething);

The task will be synchronously called if the dispatcher is shutdown.

Defined at line 194 of file ../../sdk/lib/async_patterns/cpp/dispatcher_bound.h

void DispatcherBound<T> (DispatcherBound<T> && )

Typically, asynchronous classes would contain internal self-pointers that

make moving dangerous, so we disable moves here for now.

Defined at line 208 of file ../../sdk/lib/async_patterns/cpp/dispatcher_bound.h

DispatcherBound<T> & operator= (DispatcherBound<T> && )

Defined at line 209 of file ../../sdk/lib/async_patterns/cpp/dispatcher_bound.h

void DispatcherBound<T> (const DispatcherBound<T> & )

Defined at line 211 of file ../../sdk/lib/async_patterns/cpp/dispatcher_bound.h

DispatcherBound<T> & operator= (const DispatcherBound<T> & )

Defined at line 212 of file ../../sdk/lib/async_patterns/cpp/dispatcher_bound.h

void ~DispatcherBound<T> ()

If |has_value|, asynchronously destroys the managed |T| on a task

posted to the dispatcher.

If the dispatcher is shutdown, |T| will be synchronously destroyed.

Defined at line 218 of file ../../sdk/lib/async_patterns/cpp/dispatcher_bound.h

void reset ()

If |has_value|, asynchronously destroys the managed |T| on a task

posted to the dispatcher.

If the dispatcher is shutdown, |T| will be synchronously destroyed.

Defined at line 224 of file ../../sdk/lib/async_patterns/cpp/dispatcher_bound.h

bool has_value ()

Returns if this object holds an instance of |T|.

Defined at line 232 of file ../../sdk/lib/async_patterns/cpp/dispatcher_bound.h

Protected Methods

template <template <typename, typename, typename> typename Builder = PendingCall, typename Callable, typename... Args>
auto UnsafeAsyncCallImpl (Callable && callable, Args &&... args)

Calls an arbitrary |callable| asynchronously on the |dispatcher_|.

Defined at line 238 of file ../../sdk/lib/async_patterns/cpp/dispatcher_bound.h

template <typename... Args>
void CheckArgs (fit::parameter_pack<Args...> )

Defined at line 245 of file ../../sdk/lib/async_patterns/cpp/dispatcher_bound.h