1 ! Copyright (C) 2008, 2010 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors sequences assocs arrays continuations
4 destructors combinators kernel threads concurrency.messaging
5 concurrency.mailboxes concurrency.promises io.files io.files.info
6 io.directories io.pathnames io.monitors io.monitors.private
8 IN: io.monitors.recursive
10 ! Simulate recursive monitors on platforms that don't have them
12 TUPLE: recursive-monitor < monitor children thread ready ;
14 : notify? ( -- ? ) monitor tget ready>> promise-fulfilled? ;
16 DEFER: add-child-monitor
18 : qualify-path ( path -- path' )
19 monitor tget path>> prepend-path ;
21 : add-child-monitors ( path -- )
22 ! We yield since this directory scan might take a while.
24 [ append-path ] with map
25 [ add-child-monitor ] each yield
26 ] with-directory-files ;
28 : add-child-monitor ( path -- )
29 notify? [ dup { +add-file+ } monitor tget queue-change ] when
30 qualify-path dup link-info directory? [
31 [ add-child-monitors ]
34 _ [ f my-mailbox (monitor) ] keep
35 monitor tget children>> set-at
40 : remove-child-monitor ( monitor -- )
41 monitor tget children>> delete-at* [ dispose ] [ drop ] if ;
45 M: recursive-monitor dispose*
46 [ [ +stop+ ] dip thread>> send ] [ call-next-method ] bi ;
49 monitor tget children>> values dispose-each ;
51 : pump-step ( msg -- )
52 monitor tget disposed>> [ drop ] [
53 [ [ monitor>> path>> ] [ path>> ] bi append-path ] [ changed>> ] bi
54 monitor tget queue-change
57 : child-added ( path monitor -- )
58 path>> prepend-path add-child-monitor ;
60 : child-removed ( path monitor -- )
61 path>> prepend-path remove-child-monitor ;
63 : update-hierarchy ( msg -- )
64 [ path>> ] [ monitor>> ] [ changed>> ] tri [
66 { +add-file+ [ child-added ] }
67 { +remove-file+ [ child-removed ] }
68 { +rename-file-old+ [ child-removed ] }
69 { +rename-file-new+ [ child-added ] }
76 { [ dup +stop+ eq? ] [ drop stop-pump ] }
77 { [ dup monitor-disposed eq? ] [ drop ] }
79 [ '[ _ update-hierarchy ] ignore-errors ] [ pump-step ] bi
84 : monitor-ready ( error/t -- )
85 monitor tget ready>> fulfill ;
87 : pump-thread ( monitor -- )
89 [ "" add-child-monitor t monitor-ready ]
90 [ [ self <linked-error> monitor-ready ] keep rethrow ]
94 : start-pump-thread ( monitor -- )
95 dup '[ _ pump-thread ]
96 "Recursive monitor pump" spawn
99 : wait-for-ready ( monitor -- )
100 ready>> ?promise ?linked drop ;
102 : <recursive-monitor> ( path mailbox -- monitor )
104 [ absolute-path ] dip
105 recursive-monitor new-monitor |dispose
106 H{ } clone >>children
108 dup start-pump-thread