1 #+TITLE: Concurrent Propagator System
2 #+OPTIONS: num:nil ^:nil
7 :tangle: src/propagator.clj
12 #^{:author "Eric Schulte",
14 :doc "Simple concurrent propagator system."}
16 (:use clojure.contrib.repl-utils
17 clojure.contrib.duck-streams))
19 (defmacro cell "Define a new cell."
21 `(def ~name (agent ~state)))
23 (defmacro propagator "Define a new propagator."
24 [name in-cells out-cells & body]
26 (defn ~(with-meta name
28 :in-cells in-cells :out-cells out-cells))
30 (doseq [cell# ~in-cells]
31 (println (format "adding %S to %S" ~name cell#))
32 (add-neighbor cell# ~name))
35 (defmacro run-propagator
36 "Run a propagator, first collect the most recent values from all
37 cells associated with the propagator, then evaluate."
39 `(let [run-me# (fn [_#]
40 (apply ~propagator (map deref (:in-cells ^#'~propagator))))]
41 (map (fn [cell#] (send cell# run-me#)) (:out-cells ^#'~propagator))))
43 (defmacro add-neighbor "Add a neighbor to the given cell."
49 (run-propagator ~neighbor)
50 (append-spit "/home/Desktop/spitoon" (~neighbor))
56 ** look at mutable data stores
57 - http://clojure.org/agents
58 - http://clojure.org/atoms
59 - http://clojure.org/refs
61 most definitely will use agents, functions to set their values are
62 applied to them with send (or send-off if potentially I/O bound), they
63 support validators, and they can be set to run actions (i.e. alert
64 propagators) as part of their update cycle.
66 ** design to permit distribution across multiple machines
67 it should be possible to wrap these mutable items including
68 - network connections from other machines
69 - hardware (timers, I/O devices, etc...)
71 in cells, so that the propagator system remains "pure"
74 This probably mentioned a request for advice from the mailing list or
75 from the #clojure group.