Advertisement
Guest User

Untitled

a guest
Dec 15th, 2011
202
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. (ns lcc-clojure.actors
  2.   (:require [lcc-clojure.log :as log]))
  3.  
  4. (def ^{:dynamic true} *log* (log/log-to-file "/tmp/actors-log"))
  5. (def ^{:dynamic true :private true} *actors* (atom {}))
  6.  
  7. (def ^{:dynamic true :private true} *self*)
  8.  
  9. (defn msg
  10.   ([clause payload]
  11.      {:clause clause :payload payload})
  12.   ([clause]
  13.      (msg clause nil)))
  14.  
  15. (defn msg-handler
  16.   "Returns the handler for the incoming message. Returns nil if the message is not listed as a valid clause."
  17.   [clauses msg]
  18.   (get clauses msg))
  19.  
  20. (defn act
  21.   "Act message sent to actors to react to an incoming message."
  22.   [old-f msg & payload]
  23.   (when (fn? old-f)
  24.     (old-f old-f msg)))
  25.  
  26. (defn receive
  27.   "Receive is the main spirit of actors. It takes a map where keys are the messages and values the corresponding handlers."
  28.   [clauses]
  29.   {:pre (map? clauses)}
  30.   (fn [old-f msg]
  31.     (if-let [f (msg-handler clauses (:clause msg))]
  32.       (f (:payload msg))
  33.       old-f)))
  34.  
  35. (defmacro handle
  36.   "Defines a handler for an incoming message."
  37.   [& body]
  38.   `(fn [& ~'msgs]
  39.      (do ~@body)))
  40.  
  41. (defmacro handle-named
  42.   [[msgs-name] & body]
  43.   `(fn [msgs#]
  44.      (let [~msgs-name msgs#] ~@body)))
  45.  
  46. (defn !
  47.   "Sends the actor message msg."
  48.   ([actor clause]
  49.      (send actor act (msg clause)))
  50.   ([actor clause payload]
  51.      (send actor act (msg clause payload))))
  52.  
  53. (defn !-
  54.   "Looks up the actor by name in the registry and then sends it the message msg."
  55.   ([name msg]
  56.      (when-let [actor (get @*actors* name)]
  57.        (! actor msg)))
  58.   ([name msg payload]
  59.      (when-let [actor (get @*actors* name)]
  60.        (! actor msg payload))))
  61.  
  62. (defn all-actors
  63.   "Returns a list of all registered actors."
  64.   []
  65.   (vals @*actors*))
  66.  
  67. (defn clear-actors
  68.   "Clears the actors' registry."
  69.   []
  70.   (reset! *actors* {}))
  71.  
  72. (defmacro with-name [name & body]
  73.   `(let [~'*self* ~name]
  74.      ~@body) )
  75.  
  76. (defn spawn
  77.   "Spawns and registers a new named actor with handler f."
  78.   [name f & args]
  79.   (let [actor (agent nil)]
  80.     (swap! *actors* assoc name actor)
  81.     (send-off actor (fn [_] (with-name name
  82.                              (apply f args))))
  83.     (await actor)
  84.     actor))
  85.  
  86. ;;; ping-pong example
  87.  
  88. (defn pong []
  89.   (receive {:ping (fn [payload]
  90.                     (do (println "[PONG] payload:" payload)
  91.                         (println *self*)
  92.                         (!- "ping" :pong)
  93.                         (pong)))
  94.             :stop (fn [& _] (println "[PONG] stopping."))}))
  95.  
  96.  
  97. (defn ping [n]
  98.   (if (zero? n)
  99.     (do (!- "pong" :stop)
  100.         (println "[PING] done."))
  101.     (do (!- "pong" :ping)
  102.         (receive {:pong (fn [payload]
  103.                           (println "[PING] pong received.")
  104.                           (ping (dec n)))}))))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement