cpl 2016 week 14
play

CPL 2016, week 14 Clojure agents Oleg Batrashev Institute of - PowerPoint PPT Presentation

CPL 2016, week 14 Clojure agents Oleg Batrashev Institute of Computer Science, Tartu, Estonia May 9, 2016 Overview Last weeks Clojure language core Immutable data structures Clojure simple state and design Software


  1. CPL 2016, week 14 Clojure agents Oleg Batrashev Institute of Computer Science, Tartu, Estonia May 9, 2016

  2. Overview Last weeks ◮ Clojure language core ◮ Immutable data structures ◮ Clojure simple state and design ◮ Software transactional memory (STM) This week ◮ Agents in Clojure

  3. Clojure agents 81/90 - Scope ◮ Agent programming is a term used in many contexts ◮ concurrent entities ◮ intelligent agents ◮ agents with goals ◮ cooperating agents ◮ etc We are primarly interested in properties arising from concurrency.

  4. Clojure agents 82/90 - General ◮ Agent in Clojure is a reference type (mutable holding state) that can be changed by sending it an action (function) ◮ uncoordinated – independent of changes of other agents ◮ asynchronous – changes are away from the thread that schedules an action ◮ immediate return: no wait for the completion of an action ◮ 2 characteristics of Clojure agents ◮ I/O may be used safely with agents unlike in STM ◮ agents are STM aware

  5. Clojure agents 83/90 - Agent mechanics ◮ reading agent’s state deref / @ – non-blocking ◮ (send a action-fn & args) – send agent a an action ◮ action-fn takes agent state, args and returns new agent state ◮ as with (apply action-fn state-of-agent args) ◮ actions are stored into the queue for each agent ◮ processed sequentially by threads, mutating its state ◮ thread from one of two thread pools ◮ thread pools ◮ fixed size – actions delivered from send ◮ unlimited size – actions delivered from send-off ◮ needed for blocking IO

  6. Clojure agents 84/90 - Agent example ◮ agent with the state of single integer – counter ◮ await is only needed to show the result, in general agents must be asynchronous (def counterAgent (agent 0)) (send counterAgent inc) (send counterAgent (fn [state] (+ state 3))) (send counterAgent (fn [state msg] (+ state msg )) 10) (await counterAgent ) (println @counterAgent )

  7. Clojure agents 85/90 - Diagram ◮ black actions are CPU bound (send) ◮ threads t 2 and t 3 are from fixed size pool ◮ threads t 18 and t 9 are from unbounded pool ◮ for single agent all actions still are sequential, although may be running in different threads ◮ *agent* is the agent currently run by the thread

  8. Clojure agents 86/90 - Semantics of agents ◮ agents != threads ◮ usually number of threads <‌< number of agents ◮ agents still run concurrently -> green threads ◮ not as in typical Remote Procedure Call (RPC), where ◮ allow to enter multiple threads instead of one ◮ state is not declarative ◮ reduce – value from a list + operation = action (fun + args) ◮ intermediate reduction values = states ◮ await / await-for – wait for all actions from current thread to complete

  9. Clojure agents 87/90 - Errors in agents ◮ agent on exception goes to error state ◮ agent-error returns exception or nil ◮ sending actions to agent throw the exception ◮ (restart-agent agent new-state & options) – clears error state ◮ :clear-actions also clears the action queue ◮ when creating an agent ◮ :error-mode , either :fail (default) or :continue ◮ agent is not failed on ’continue’ mode ◮ :error-handler – provide function that is called in ’continue’ mode ◮ set-error-mode!, set-error-handler!

  10. Clojure agents 88/90 - IO/STM/nested sends ◮ synchronization point for IO ◮ exclusive access to file,socket,stream ◮ others schedule actions on this agent ◮ unlike refs/atoms that should avoid side-effects because of possible transaction restarts ◮ STM aware: any actions sent within a transaction are held until it commits ◮ nested send: any actions sent within an agent are withheld until current action is finished

  11. Clojure agents 89/90 - Watches ◮ watch the reference (atom, ref, or agent) ◮ watch – function that is called when the reference is changed (defn watchFun [key identity old new] (println identity "changed value from " old "to" new )) (def counterAgent (agent 0)) (add -watch counterAgent :mywatch watchFun) (send counterAgent inc) (send counterAgent (fn [state] (+ state 3))) (send counterAgent (fn [state msg] (+ state msg )) 10) ◮ identity is atom, ref, or agent ◮ key allows to attach several watch functions and detach them ◮ identity may already have different value, when watch function is called

  12. Clojure agents 90/90 - Example: log the game ◮ Add watchers to game atoms, refs ◮ watchers send states to logging agent(s) ◮ watcher callback is called in the transaction thread, presumably before releasing the ref ◮ correct order of ref states are queued to the agent(s) ◮ logging game changes and not states requires interception of game methods ◮ must be done (!) in the transaction because of possible transaction restarts ◮ log action is delayed until commit

Recommend


More recommend