1 | #pragma once |
2 | |
3 | #include <mbgl/actor/mailbox.hpp> |
4 | #include <mbgl/actor/message.hpp> |
5 | |
6 | #include <memory> |
7 | |
8 | namespace mbgl { |
9 | |
10 | /* |
11 | An `ActorRef<O>` is a *non*-owning, weak reference to an actor of type `O`. You can send it |
12 | messages just like an `Actor<O>`. It's a value object: safe to copy and pass between actors |
13 | via messages. |
14 | |
15 | An `ActorRef<O>` does not extend the lifetime of the corresponding `Actor<O>`. That's determined |
16 | entirely by whichever object owns the `Actor<O>` -- the actor's "supervisor". |
17 | |
18 | It's safe for a `Ref` to outlive its `Actor` -- the reference is "weak", and does not extend |
19 | the lifetime of the owning Actor, and sending a message to a `Ref` whose `Actor` has died is |
20 | a no-op. (In the future, a dead-letters queue or log may be implemented.) |
21 | */ |
22 | |
23 | template <class Object> |
24 | class ActorRef { |
25 | public: |
26 | ActorRef(Object& object_, std::weak_ptr<Mailbox> weakMailbox_) |
27 | : object(&object_), |
28 | weakMailbox(std::move(weakMailbox_)) { |
29 | } |
30 | |
31 | template <typename Fn, class... Args> |
32 | void invoke(Fn fn, Args&&... args) { |
33 | if (auto mailbox = weakMailbox.lock()) { |
34 | mailbox->push(actor::makeMessage(*object, fn, std::forward<Args>(args)...)); |
35 | } |
36 | } |
37 | |
38 | template <typename Fn, class... Args> |
39 | auto ask(Fn fn, Args&&... args) { |
40 | // Result type is deduced from the function's return type |
41 | using ResultType = typename std::result_of<decltype(fn)(Object, Args...)>::type; |
42 | |
43 | std::promise<ResultType> promise; |
44 | auto future = promise.get_future(); |
45 | |
46 | if (auto mailbox = weakMailbox.lock()) { |
47 | mailbox->push( |
48 | actor::makeMessage( |
49 | std::move(promise), *object, fn, std::forward<Args>(args)... |
50 | ) |
51 | ); |
52 | } else { |
53 | promise.set_exception(std::make_exception_ptr(ex: std::runtime_error("Actor has gone away" ))); |
54 | } |
55 | |
56 | return future; |
57 | } |
58 | |
59 | private: |
60 | Object* object; |
61 | std::weak_ptr<Mailbox> weakMailbox; |
62 | }; |
63 | |
64 | } // namespace mbgl |
65 | |