summaryrefslogtreecommitdiff
path: root/include/mbgl/actor/aspiring_actor.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/mbgl/actor/aspiring_actor.hpp')
-rw-r--r--include/mbgl/actor/aspiring_actor.hpp60
1 files changed, 60 insertions, 0 deletions
diff --git a/include/mbgl/actor/aspiring_actor.hpp b/include/mbgl/actor/aspiring_actor.hpp
new file mode 100644
index 0000000000..6c410cdfca
--- /dev/null
+++ b/include/mbgl/actor/aspiring_actor.hpp
@@ -0,0 +1,60 @@
+#pragma once
+
+#include <mbgl/actor/mailbox.hpp>
+#include <mbgl/actor/message.hpp>
+#include <mbgl/actor/actor_ref.hpp>
+
+#include <memory>
+#include <future>
+#include <type_traits>
+#include <cassert>
+
+namespace mbgl {
+
+template <class Object>
+class EstablishedActor;
+
+template <class Object>
+class Actor;
+
+/*
+ An `AspiringActor<O>` is one half of the pair of types that comprise an actor (see `Actor<O>`),
+ the other half being `EstablishedActor<O>`. It 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<O>` can
+ accept messages for the target object, or provide `ActorRef<O>`s that do so, before the object
+ has actually been constructed by the corresponding `EstablishedActor<O>`. (Such messages are
+ queued in the mailbox until after the object is constructed.)
+
+ This allows for an `AspiringActor<O>` to be created and safely used by a thread other than the
+ one on which the target object will (eventually) live.
+*/
+template <class Object>
+class AspiringActor {
+public:
+ AspiringActor() : mailbox(std::make_shared<Mailbox>()) {
+ // mailbox starts closed because the `Object` hasn't yet been constructed
+ assert(!mailbox->isOpen());
+ }
+
+ AspiringActor(const AspiringActor&) = delete;
+
+ ActorRef<std::decay_t<Object>> self() {
+ return ActorRef<std::decay_t<Object>>(object(), mailbox);
+ }
+
+private:
+ std::shared_ptr<Mailbox> mailbox;
+ std::aligned_storage_t<sizeof(Object)> objectStorage;
+
+ Object& object() {
+ return *reinterpret_cast<Object *>(&objectStorage);
+ }
+
+ friend class EstablishedActor<Object>;
+ friend class Actor<Object>;
+};
+
+} // namespace mbgl