syndicate-2017/racket/syndicate/examples/actor/file-system-lll2.rkt

51 lines
2.2 KiB
Racket

#lang syndicate
;; Toy file system, based on the example in the ESOP2016 submission.
;; Low-level implementation, without subconversation.
(require/activate "fs-shell.rkt")
(require/activate "fs-protocol.rkt")
(require (only-in syndicate [assert core:assert]))
(require racket/set)
(struct fs-state (files monitored) #:prefab)
(define (update-file state name new-content)
(transition (struct-copy fs-state state
[files (if new-content
(hash-set (fs-state-files state) name new-content)
(hash-remove (fs-state-files state) name))])
(if (set-member? (fs-state-monitored state) name)
(patch-seq (retract (file name (hash-ref (fs-state-files state) name #f)))
(core:assert (file name new-content)))
'())))
(define (file-system-event-handler e state)
(match e
[(? patch? p)
(define monitored-to-add
(for-trie/set [((observe (file $name _)) (patch-added p))] name))
(define monitored-to-remove
(for-trie/set [((observe (file $name _)) (patch-removed p))] name))
(transition (struct-copy fs-state state
[monitored (set-subtract (set-union (fs-state-monitored state)
monitored-to-add)
monitored-to-remove)])
(list (for/list [(name monitored-to-add)]
(printf "At least one reader exists for ~v\n" name)
(core:assert (file name (hash-ref (fs-state-files state) name #f))))
(for/list [(name monitored-to-remove)]
(printf "No remaining readers exist for ~v\n" name)
(retract (file name ?)))))]
[(message (save (file name new-content)))
(update-file state name new-content)]
[(message (delete name))
(update-file state name #f)]
[_ #f]))
(spawn file-system-event-handler
(fs-state (hash) (set))
(patch-seq (sub (observe (file ? ?)))
(sub (save (file ? ?)))
(sub (delete ?))))