factor/basis/io/monitors/recursive/recursive.factor

109 lines
3.0 KiB
Factor
Raw Normal View History

! Copyright (C) 2008, 2010 Slava Pestov.
2008-04-11 08:15:26 -04:00
! See http://factorcode.org/license.txt for BSD license.
2008-05-15 00:23:12 -04:00
USING: accessors sequences assocs arrays continuations
destructors combinators kernel threads concurrency.messaging
concurrency.mailboxes concurrency.promises io.files io.files.info
io.directories io.pathnames io.monitors io.monitors.private
debugger fry ;
2008-04-11 08:15:26 -04:00
IN: io.monitors.recursive
! Simulate recursive monitors on platforms that don't have them
TUPLE: recursive-monitor < monitor children thread ready ;
2008-04-11 08:15:26 -04:00
2008-04-21 07:13:57 -04:00
: notify? ( -- ? ) monitor tget ready>> promise-fulfilled? ;
2008-04-11 08:15:26 -04:00
DEFER: add-child-monitor
: qualify-path ( path -- path' )
monitor tget path>> prepend-path ;
: add-child-monitors ( path -- )
#! We yield since this directory scan might take a while.
2008-10-19 19:30:51 -04:00
dup [
[ append-path ] with map
2008-10-19 14:09:48 -04:00
[ add-child-monitor ] each yield
] with-directory-files ;
2008-04-11 08:15:26 -04:00
: add-child-monitor ( path -- )
2008-04-21 07:13:57 -04:00
notify? [ dup { +add-file+ } monitor tget queue-change ] when
2008-10-19 14:09:48 -04:00
qualify-path dup link-info directory? [
2008-04-11 08:15:26 -04:00
[ add-child-monitors ]
[
'[
_ [ f my-mailbox (monitor) ] keep
2008-04-21 07:13:57 -04:00
monitor tget children>> set-at
] ignore-errors
2008-04-11 08:15:26 -04:00
] bi
] [ drop ] if ;
: remove-child-monitor ( monitor -- )
2008-04-21 07:13:57 -04:00
monitor tget children>> delete-at* [ dispose ] [ drop ] if ;
2008-04-11 08:15:26 -04:00
SYMBOL: +stop+
2008-05-15 00:23:12 -04:00
M: recursive-monitor dispose*
[ [ +stop+ ] dip thread>> send ] [ call-next-method ] bi ;
2008-04-11 08:15:26 -04:00
: stop-pump ( -- )
monitor tget children>> values dispose-each ;
2008-04-11 08:15:26 -04:00
: pump-step ( msg -- )
2010-08-24 00:54:59 -04:00
monitor tget disposed>> [ drop ] [
[ [ monitor>> path>> ] [ path>> ] bi append-path ] [ changed>> ] bi
monitor tget queue-change
2010-08-24 00:54:59 -04:00
] if ;
2008-04-11 08:15:26 -04:00
: child-added ( path monitor -- )
path>> prepend-path add-child-monitor ;
: child-removed ( path monitor -- )
path>> prepend-path remove-child-monitor ;
: update-hierarchy ( msg -- )
[ path>> ] [ monitor>> ] [ changed>> ] tri [
2008-04-11 08:15:26 -04:00
{
{ +add-file+ [ child-added ] }
{ +remove-file+ [ child-removed ] }
{ +rename-file-old+ [ child-removed ] }
{ +rename-file-new+ [ child-added ] }
[ 3drop ]
} case
] with with each ;
: pump-loop ( -- )
receive {
{ [ dup +stop+ eq? ] [ drop stop-pump ] }
{ [ dup monitor-disposed eq? ] [ drop ] }
[
[ '[ _ update-hierarchy ] ignore-errors ] [ pump-step ] bi
pump-loop
]
} cond ;
2008-04-11 08:15:26 -04:00
: monitor-ready ( error/t -- )
monitor tget ready>> fulfill ;
: pump-thread ( monitor -- )
monitor tset
[ "" add-child-monitor t monitor-ready ]
[ [ self <linked-error> monitor-ready ] keep rethrow ]
recover
pump-loop ;
: start-pump-thread ( monitor -- )
dup '[ _ pump-thread ]
2008-04-11 08:15:26 -04:00
"Recursive monitor pump" spawn
>>thread drop ;
: wait-for-ready ( monitor -- )
ready>> ?promise ?linked drop ;
: <recursive-monitor> ( path mailbox -- monitor )
[ absolute-path ] dip
recursive-monitor new-monitor
2008-04-11 08:15:26 -04:00
H{ } clone >>children
<promise> >>ready
dup start-pump-thread
dup wait-for-ready ;