| 
									
										
										
										
											2008-04-11 08:15:26 -04:00
										 |  |  | ! Copyright (C) 2008 Slava Pestov. | 
					
						
							|  |  |  | ! 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.monitors | 
					
						
							|  |  |  | debugger ;
 | 
					
						
							| 
									
										
										
										
											2008-04-11 08:15:26 -04:00
										 |  |  | IN: io.monitors.recursive | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! Simulate recursive monitors on platforms that don't have them | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-15 00:23:12 -04:00
										 |  |  | TUPLE: recursive-monitor < monitor children thread ready disposed ;
 | 
					
						
							| 
									
										
										
										
											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 ] | 
					
						
							|  |  |  |         [ | 
					
						
							| 
									
										
										
										
											2008-04-21 07:13:57 -04:00
										 |  |  |             [ | 
					
						
							|  |  |  |                 [ f my-mailbox (monitor) ] keep
 | 
					
						
							|  |  |  |                 monitor tget children>> set-at
 | 
					
						
							|  |  |  |             ] curry 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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-15 00:23:12 -04:00
										 |  |  | M: recursive-monitor dispose* | 
					
						
							|  |  |  |     [ "stop" swap thread>> send-synchronous drop ] | 
					
						
							|  |  |  |     [ queue>> dispose ] | 
					
						
							|  |  |  |     bi ;
 | 
					
						
							| 
									
										
										
										
											2008-04-11 08:15:26 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : stop-pump ( -- )
 | 
					
						
							|  |  |  |     monitor tget children>> [ nip dispose ] assoc-each ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : pump-step ( msg -- )
 | 
					
						
							|  |  |  |     first3 path>> swap >r prepend-path r> monitor tget 3array
 | 
					
						
							|  |  |  |     monitor tget queue>> | 
					
						
							|  |  |  |     mailbox-put ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : child-added ( path monitor -- )
 | 
					
						
							|  |  |  |     path>> prepend-path add-child-monitor ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : child-removed ( path monitor -- )
 | 
					
						
							|  |  |  |     path>> prepend-path remove-child-monitor ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : update-hierarchy ( msg -- )
 | 
					
						
							|  |  |  |     first3 swap [ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             { +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 synchronous? [ | 
					
						
							|  |  |  |         >r stop-pump t r> reply-synchronous | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         [ [ update-hierarchy ] curry ignore-errors ] [ pump-step ] bi
 | 
					
						
							|  |  |  |         pump-loop | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : 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 ] curry
 | 
					
						
							|  |  |  |     "Recursive monitor pump" spawn | 
					
						
							|  |  |  |     >>thread drop ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : wait-for-ready ( monitor -- )
 | 
					
						
							|  |  |  |     ready>> ?promise ?linked drop ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : <recursive-monitor> ( path mailbox -- monitor )
 | 
					
						
							|  |  |  |     >r (normalize-path) r> | 
					
						
							| 
									
										
										
										
											2008-04-14 06:07:31 -04:00
										 |  |  |     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 ;
 |