Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (ns lcc-clojure.actors
- (:require [lcc-clojure.log :as log]))
- (def ^{:dynamic true} *log* (log/log-to-file "/tmp/actors-log"))
- (def ^{:dynamic true :private true} *actors* (atom {}))
- (def ^{:dynamic true :private true} *self*)
- (defn msg
- ([clause payload]
- {:clause clause :payload payload})
- ([clause]
- (msg clause nil)))
- (defn msg-handler
- "Returns the handler for the incoming message. Returns nil if the message is not listed as a valid clause."
- [clauses msg]
- (get clauses msg))
- (defn act
- "Act message sent to actors to react to an incoming message."
- [old-f msg & payload]
- (when (fn? old-f)
- (old-f old-f msg)))
- (defn receive
- "Receive is the main spirit of actors. It takes a map where keys are the messages and values the corresponding handlers."
- [clauses]
- {:pre (map? clauses)}
- (fn [old-f msg]
- (if-let [f (msg-handler clauses (:clause msg))]
- (f (:payload msg))
- old-f)))
- (defmacro handle
- "Defines a handler for an incoming message."
- [& body]
- `(fn [& ~'msgs]
- (do ~@body)))
- (defmacro handle-named
- [[msgs-name] & body]
- `(fn [msgs#]
- (let [~msgs-name msgs#] ~@body)))
- (defn !
- "Sends the actor message msg."
- ([actor clause]
- (send actor act (msg clause)))
- ([actor clause payload]
- (send actor act (msg clause payload))))
- (defn !-
- "Looks up the actor by name in the registry and then sends it the message msg."
- ([name msg]
- (when-let [actor (get @*actors* name)]
- (! actor msg)))
- ([name msg payload]
- (when-let [actor (get @*actors* name)]
- (! actor msg payload))))
- (defn all-actors
- "Returns a list of all registered actors."
- []
- (vals @*actors*))
- (defn clear-actors
- "Clears the actors' registry."
- []
- (reset! *actors* {}))
- (defmacro with-name [name & body]
- `(let [~'*self* ~name]
- ~@body) )
- (defn spawn
- "Spawns and registers a new named actor with handler f."
- [name f & args]
- (let [actor (agent nil)]
- (swap! *actors* assoc name actor)
- (send-off actor (fn [_] (with-name name
- (apply f args))))
- (await actor)
- actor))
- ;;; ping-pong example
- (defn pong []
- (receive {:ping (fn [payload]
- (do (println "[PONG] payload:" payload)
- (println *self*)
- (!- "ping" :pong)
- (pong)))
- :stop (fn [& _] (println "[PONG] stopping."))}))
- (defn ping [n]
- (if (zero? n)
- (do (!- "pong" :stop)
- (println "[PING] done."))
- (do (!- "pong" :ping)
- (receive {:pong (fn [payload]
- (println "[PING] pong received.")
- (ping (dec n)))}))))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement