Permalink
Browse files

Delete slots add, main + Add slots lock, cv, behavior

add() and main() functions were removed from the class and made into individual methods.

Consequently lock, cv and behavior() which would be required by actor.add() and
actor.main() methods are brought into the actor class for access by the methods.

Also get-add and consequent logic is put into actor.send() method
  • Loading branch information...
1 parent a8d206f commit bd1cf721c4da93cf62364c418c74b5c6bcb2e60a @nixz nixz committed May 10, 2012
Showing with 45 additions and 40 deletions.
  1. +45 −40 actors.lisp
View
85 actors.lisp
@@ -6,31 +6,46 @@
:initform (error ":name must be specified")
:accessor name
:documentation "Hold the name of actor")
- (add :initarg :add
- :initform (error ":add must be specified")
- :accessor add
- :documentation "holds handle to add method")
- (main :initarg :main
- :initform (error ":main must be specified")
- :accessor main
- :documentation "Main Thread")
- (messages :initarg :messages
- :initform (error ":messages must be specified")
+ (behavior :initarg :behavior
+ :initform (error ":behav must be specified")
+ :accessor behavior
+ :documentation "Behavior")
+ (messages :initform '()
:accessor messages
:documentation "Message stream sent to actor")
+ (lock :initform (bt:make-lock)
+ :accessor lock
+ :documentation
+ "The lock is used when adding a message to the message queue")
+ (cv :initarg :cv
+ :initform (bt:make-condition-variable)
+ :accessor cv
+ :documentation "conditional variable used by the thread")
thread))
;; ----------------------------------------------------------------------------
(defmethod initialize-instance :after((self actor) &key)
"Uses the main functiona name to create a thread"
- (with-slots (name main thread) self
+ (with-slots (name thread) self
(setf thread
- (bt:make-thread main :name name))))
+ (bt:make-thread #'(lambda() (main self))
+ :name name))))
;; ----------------------------------------------------------------------------
(defmethod send ((self actor) &rest message)
- (bt:make-thread #'(lambda () (funcall (get-add self) message)))
- (values))
+ "
+Creates a message sending thread which
+1. Holds lock to the message (queue)
+2. Appends messages (queue) with incoming message
+3. Releases lock
+4. Notifies the waiting thread that there is a message
+"
+ (with-slots (messages lock cv) self
+ (bt:make-thread #'(lambda ()
+ (with-lock-held (lock)
+ (setf messages (nconc messages (list message))))
+ (condition-notify cv)))
+ (values)))
;; ----------------------------------------------------------------------------
;; (defun stop-actor (actor) (destroy-thread (get-thread actor)))
@@ -47,11 +62,19 @@
thread))
;; ----------------------------------------------------------------------------
-;; (defun get-add (actor) (second actor))
-(defmethod get-add ((self actor))
- "Returns handle to the add function"
- (with-slots (add) self
- add))
+;; The main which is started as a thread from the constructor I think that this
+;; should be more of an internal function than a method (experiment with
+;; funcallable-standard-class)
+(defmethod main((self actor))
+ (with-slots (lock cv (behav behavior) messages) self
+ (loop
+ (thread-yield)
+ (with-lock-held (lock)
+ (if (not (null messages))
+ (setf behav (apply behav
+ (pop messages)))
+ (condition-wait cv lock ))
+ (unless behav (return))))))
;; ----------------------------------------------------------------------------
;; Create a behavior that can be attached to any actor
@@ -75,27 +98,9 @@
;; ----------------------------------------------------------------------------
;; The shell of an actor
(defun make-actor (behav name)
- (let (self
- (lock (bt:make-lock))
- (messages '())
- (cv (bt:make-condition-variable)))
- (labels ((add (m)
- (with-lock-held (lock)
- (setf messages (nconc messages (list m))))
- (condition-notify cv))
- (run-actor () (loop
- (thread-yield)
- (with-lock-held (lock)
- (if (not (null messages))
- (setf behav (apply behav
- (pop messages)))
- (condition-wait cv lock ))
- (unless behav (return))))))
- (setf self (make-instance 'actor
- :name (concatenate 'string "Actor: " name)
- :main #'run-actor
- :add #'add
- :messages messages)))))
+ (make-instance 'actor
+ :name (concatenate 'string "Actor: " name)
+ :behavior behav))
;; ----------------------------------------------------------------------------
(defun if-single (x)

0 comments on commit bd1cf72

Please sign in to comment.