From a942befc652cdd28a4df8b8c6ea5d0f50aef3134 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Wed, 19 May 2021 14:00:48 +0200 Subject: [PATCH] Add more agent vars (#857) --- src/babashka/impl/clojure/core.clj | 52 ++++++++++++++++++++++++++++-- test/babashka/agent_test.clj | 10 ++++++ 2 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 test/babashka/agent_test.clj diff --git a/src/babashka/impl/clojure/core.clj b/src/babashka/impl/clojure/core.clj index 7938df6d..a04cb381 100644 --- a/src/babashka/impl/clojure/core.clj +++ b/src/babashka/impl/clojure/core.clj @@ -1,11 +1,14 @@ (ns babashka.impl.clojure.core {:no-doc true} - (:refer-clojure :exclude [future read+string clojure-version with-precision]) + (:refer-clojure :exclude [future read+string clojure-version with-precision + send-via send send-off]) (:require [babashka.impl.common :as common] [borkdude.graal.locking :as locking] + [clojure.core :as c] [clojure.string :as str] [sci.core :as sci] - [sci.impl.namespaces :refer [copy-core-var clojure-core-ns]])) + [sci.impl.namespaces :refer [copy-core-var clojure-core-ns]] + [sci.impl.vars :as vars])) (defn locking* [form bindings v f & args] (apply @#'locking/locking form bindings v f args)) @@ -89,11 +92,54 @@ (binding [*math-context* math-context] (body-fn))) + +;;;; Agents + +(defn send-via + "Dispatch an action to an agent. Returns the agent immediately. + Subsequently, in a thread supplied by executor, the state of the agent + will be set to the value of: + (apply action-fn state-of-agent args)" + [executor ^clojure.lang.Agent a f & args] + (apply c/send-via executor a (vars/binding-conveyor-fn f) args)) + +(defn send + "Dispatch an action to an agent. Returns the agent immediately. + Subsequently, in a thread from a thread pool, the state of the agent + will be set to the value of: + (apply action-fn state-of-agent args)" + [^clojure.lang.Agent a f & args] + (apply send-via clojure.lang.Agent/pooledExecutor a f args)) + +(defn send-off + "Dispatch a potentially blocking action to an agent. Returns the + agent immediately. Subsequently, in a separate thread, the state of + the agent will be set to the value of: + (apply action-fn state-of-agent args)" + [^clojure.lang.Agent a f & args] + (apply send-via clojure.lang.Agent/soloExecutor a f args)) + +;;;; End agents + (def core-extras - {'file-seq (copy-core-var file-seq) + {;; agents 'agent (copy-core-var agent) + 'agent-error (copy-core-var agent-error) + 'await (copy-core-var await) + 'await-for (copy-core-var await-for) + 'error-handler (copy-core-var error-handler) + 'error-mode (copy-core-var error-mode) + 'get-validator (copy-core-var get-validator) 'send (copy-core-var send) 'send-off (copy-core-var send-off) + 'send-via (copy-core-var send-via) + 'release-pending-sends (copy-core-var release-pending-sends) + 'restart-agent (copy-core-var restart-agent) + 'set-validator! (copy-core-var set-validator!) + 'set-error-handler! (copy-core-var set-error-handler!) + 'set-error-mode! (copy-core-var set-error-mode!) + ;; end agents + 'file-seq (copy-core-var file-seq) 'promise (copy-core-var promise) 'deliver (copy-core-var deliver) 'locking (with-meta locking* {:sci/macro true}) diff --git a/test/babashka/agent_test.clj b/test/babashka/agent_test.clj new file mode 100644 index 00000000..323c8105 --- /dev/null +++ b/test/babashka/agent_test.clj @@ -0,0 +1,10 @@ +(ns babashka.agent-test + (:require + [babashka.test-utils :as test-utils] + [clojure.edn :as edn] + [clojure.test :as t :refer [deftest is]])) + +(deftest agent-binding-conveyance-test + (let [prog + "(def ^:dynamic *foo* 1) (def a (agent nil)) (binding [*foo* 2] (send-off a (fn [_] *foo*))) (await a) @a"] + (is (= 2 (edn/read-string (test-utils/bb nil prog))))))