From cfd436c287f4209d0d994042452ccbb552a6bd28 Mon Sep 17 00:00:00 2001 From: Anand Thakker Date: Tue, 3 Jul 2018 17:17:39 -0400 Subject: [core] Avoid blocking in Thread constructor (#12151) * Introduce AspiringActor, EstablishedActor This pair of objects represents the two-phase (parent-thread / child-thread) construction that's needed to support constructing Thread without blocking until the child thread is up and running. An `AspiringActor` is responsible for: - ownership of the actor's `Mailbox` - allocating the memory for (but *not* constructing) the target object `O` Using these two pieces--the mailbox and a stable address for `O`--an `AspiringActor` can accept messages for the target object, or provide `ActorRef`s that do so, before the object has actually been constructed by the corresponding `EstablishedActor`. (Such messages are queued in the mailbox until after the object is constructed.) This allows for an `AspiringActor` to be created and safely used by a thread other than the one on which the target object will (eventually) live. An `EstablishedActor` is responsible for managing the lifetime of the target object `O` and the open/closed state of the parent's `mailbox`. The `O` object's lifetime is contained by that of its owning `EstablishedActor`: the `EstablishedActor` constructor executes the `O` constructor via "placement new", constructing it at the address provided by the parent `AspiringActor`, and the `~EstablishedActor` destructor similarly executes the `~O` destructor (after closing the mailbox). `EstablishedActor` should therefore live entirely on the thread intended to own `O`. * Remove Actor#{invoke,ask} --- include/mbgl/actor/mailbox.hpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'include/mbgl/actor/mailbox.hpp') diff --git a/include/mbgl/actor/mailbox.hpp b/include/mbgl/actor/mailbox.hpp index 8ecf91701a..23c579917a 100644 --- a/include/mbgl/actor/mailbox.hpp +++ b/include/mbgl/actor/mailbox.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include #include #include @@ -11,17 +13,30 @@ class Message; class Mailbox : public std::enable_shared_from_this { public: + + // Create a "holding" mailbox, messages to which will remain queued, + // unconsumed, until the mailbox is associated with a Scheduler using + // start(). This allows a Mailbox object to be created on one thread and + // later transferred to a different target thread that may not yet exist. + Mailbox(); + Mailbox(Scheduler&); - void push(std::unique_ptr); - + // Attach the given scheduler to this mailbox and begin processing messages + // sent to it. The mailbox must be a "holding" mailbox, as created by the + // default constructor Mailbox(). + void open(Scheduler& scheduler_); void close(); + + bool isOpen() const; + + void push(std::unique_ptr); void receive(); static void maybeReceive(std::weak_ptr); private: - Scheduler& scheduler; + optional scheduler; std::recursive_mutex receivingMutex; std::mutex pushingMutex; -- cgit v1.2.1