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 }