1 /**
2 Copyright: Copyright (c) 2020, Joakim Brännström. All rights reserved.
3 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
4 Author: Joakim Brännström (joakim.brannstrom@gmx.com)
5 
6 The design is derived from C++ Actor Framework (CAF).
7 
8 Actors are always allocated with a control block that stores its identity
9 
10 When allocating a new actor, CAF will always embed the user-defined actor in an
11 `actor_storage` with the control block prefixing the actual actor type, as
12 shown below.
13 
14     +----------------------------------------+
15     |                  storage!T             |
16     +----------------------------------------+
17     | +-----------------+------------------+ |
18     | |  control block  |        data!T    | |
19     | +-----------------+------------------+ |
20     | | actor ID        | mailbox          | |
21     | | node ID         | .                | |
22     | +-----------------+------------------+ |
23     +----------------------------------------+
24 */
25 module my.actor.actor;
26 
27 import core.atomic : atomicOp, atomicLoad, atomicStore, cas;
28 import core.memory : GC;
29 import std.algorithm : move, swap;
30 
31 import my.actor : ActorSystem;
32 
33 /// Unique identifier for an actor.
34 struct ActorId {
35     ulong value;
36 }
37 
38 struct NodeId {
39     ulong value;
40 }
41 
42 class ControlBlock {
43     private {
44         ActorId aid_;
45         NodeId nid_;
46         ActorSystem* homeSystem_;
47         AbstractActor instance_;
48     }
49 
50     this(ActorId aid, NodeId nid, ActorSystem* sys) {
51         this.aid_ = aid;
52         this.nid_ = nid;
53         this.homeSystem_ = sys;
54     }
55 
56     ActorId aid() @safe pure nothrow const @nogc {
57         return aid_;
58     }
59 
60     NodeId nid() @safe pure nothrow const @nogc {
61         return nid_;
62     }
63 
64     ref ActorSystem homeSystem() @safe pure nothrow @nogc {
65         return *homeSystem_;
66     }
67 
68     /// Returns: the actual actor instance.
69     AbstractActor get() {
70         return instance_;
71     }
72 }
73 
74 /**
75 The design is derived from C++ Actor Framework (CAF).
76 
77 Actors are always allocated with a control block that stores its identity
78 
79 When allocating a new actor, CAF will always embed the user-defined actor in an
80 `actor_storage` with the control block prefixing the actual actor type, as
81 shown below.
82 
83     +----------------------------------------+
84     |                  storage!T             |
85     +----------------------------------------+
86     | +-----------------+------------------+ |
87     | |  control block  |        data!T    | |
88     | +-----------------+------------------+ |
89     | | actor ID        | mailbox          | |
90     | | node ID         | .                | |
91     | +-----------------+------------------+ |
92     +----------------------------------------+
93 */
94 struct Storage(T) {
95     ControlBlock ctrl;
96     T item;
97 
98     this(ActorId aid, NodeId nid, ActorSystem* sys, ref T item_) {
99         ctrl = new ctrl(aid, nid, sys);
100         item = move(item_);
101     }
102 
103     this(Args...)(ActorId aid, NodeId nid, ActorSystem* sys, auto ref Args args) {
104         ctrl = new ctrl(aid, nid, sys);
105         item = T(args);
106     }
107 }