3 #^{:author "Eric Schulte",
5 :doc "Simple concurrent propagator system."}
7 (:use clojure.contrib.repl-utils clojure.contrib.math))
9 (defmacro cell "Define a new cell."
11 `(def ~name (agent ~state)))
13 (defn set-cell "Set the value of a cell" [cell value]
14 (send cell (fn [_] value)))
16 (defmacro propagator "Define a new propagator."
17 [name in-cells out-cells & body]
19 (defn ~(with-meta name
21 :in-cells in-cells :out-cells out-cells))
23 (doseq [cell# ~in-cells] (add-neighbor cell# ~name))
26 (defmacro run-propagator
27 "Run a propagator, first collect the most recent values from all
28 cells associated with the propagator, then evaluate."
30 `(let [results# (apply ~propagator (map deref (:in-cells ^#'~propagator)))]
31 (doseq [cell# (:out-cells ^#'~propagator)]
32 (when (not (= @cell# results#))
33 (send cell# (fn [_#] results#))))
36 (defmacro add-neighbor "Add a neighbor to the given cell."
40 (agent nil :validator (fn [_#] (do (future (run-propagator ~neighbor)) true)))