-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathactors-comms.lisp
143 lines (106 loc) · 4.04 KB
/
actors-comms.lisp
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
(in-package #:actors-base)
;; ----------------------------------------------------------
;; Actors directory -- only for Actors with symbol names or string
;; names.
;;
;; This really ought to be an Actor-based manager! The directory is a
;; non-essential service during Actor base startup, so we will make it
;; an Actor-based service after all the base code is in place.
(defun directory-manager-p ()
(typep *actor-directory-manager* 'Actor))
;;; =========== ;;;
(defmethod acceptable-key (name)
nil)
(defmethod acceptable-key ((name (eql nil)))
nil)
(defmethod acceptable-key ((name symbol))
(and (symbol-package name)
(acceptable-key (string name))))
(defmethod acceptable-key ((name string))
(string-upcase name))
;;; =========== ;;;
(defmethod register-actor ((actor actor) name)
(when (acceptable-key name)
(send *actor-directory-manager* :register actor name)))
(defun unregister-actor (name-or-actor)
(send *actor-directory-manager* :unregister name-or-actor))
(defun get-recorded-actors ()
(when (directory-manager-p)
(ask *actor-directory-manager* :get-all)))
(defun find-actor-in-directory (name)
(when (and (directory-manager-p)
(acceptable-key name))
(ask *actor-directory-manager* :find name)))
(defmethod find-actor-name ((actor actor))
(when (directory-manager-p)
(ask *actor-directory-manager* :reverse-lookup actor)))
;; --------------------------------------------------------
;; Shared printer driver... another instance of something better
;; placed into an Actor
(defun pr (&rest things-to-print)
(apply #'send *shared-printer-actor* :print things-to-print))
;; --------------------------------------------------------------------
;; External communication with an Actor
(defmethod send (dest &rest message)
;; default to preserve semantics of quiet and no-hang sending
(declare (ignore dest message))
(values))
(defmethod send ((actor actor) &rest message)
;; send a message to an actor
(mp:mailbox-send (actor-messages actor) message)
(add-to-ready-queue actor)
(values))
(defmethod send ((mbox mp:mailbox) &rest message)
;; used by actor code to reply to ask
(mp:mailbox-send mbox message)
(values))
(defmethod send ((ch rch:channel) &rest message)
;; maybe useful??
(rch:poke ch message)
(values))
(defmethod send ((fn function) &rest message)
(apply fn message)
(values))
(defmethod send ((name (eql nil)) &rest message)
;; handle the special symbol NIL to avoid an infinite loop
(declare (ignore name message))
(values))
(defmethod send ((name symbol) &rest message)
;; this is slower, but what the heck...
(apply #'send (find-actor name) message))
(defmethod send ((name string) &rest message)
;; this is slower, but what the heck...
(apply #'send (find-actor name) message))
(defun ask (actor &rest message)
;; used to query an actor written in dlambda style
;;
;; should be wrapped with WAIT, if called from within an actor
;; behavior when the service might take a while to respond.
(let ((mb (mp:make-mailbox)))
(apply #'send actor `(,@message ,mb))
(values-list (mp:mailbox-read mb))))
;; ------------------------------------------------------------
;; Internal routines for constructing an Actor and enabling it
(defun actor-alive-p (actor)
(and (actor-behavior actor)
actor))
(defun add-actor (actor)
;; internal, used by make-actor, executive process
;; may add the actor to the ready queue
(mark-not-in-queue actor)
(when (mp:mailbox-not-empty-p (actor-messages actor))
(add-to-ready-queue actor)))
;; --------------------------------------------------------
;; Directory Introspection
(defun get-actors ()
(get-recorded-actors))
(defmethod find-actor ((actor actor))
(actor-alive-p actor))
(defun find-live-actor-in-directory (name)
(find-actor (find-actor-in-directory name)))
(defmethod find-actor ((name string))
(find-live-actor-in-directory name))
(defmethod find-actor ((name symbol))
(find-live-actor-in-directory name))
(defmethod find-actor ((actor (eql nil)))
nil)