blob: 6c410cdfcaee0b9d0e09fb51242a41abafc9b25e (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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
|