]> gitweb.factorcode.org Git - factor.git/blob - basis/io/windows/nt/monitors/monitors.factor
2680b400893fcea5315ee1030ee958cb948e719c
[factor.git] / basis / io / windows / nt / monitors / monitors.factor
1 ! Copyright (C) 2008 Doug Coleman, Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: alien alien.c-types libc destructors locals kernel math
4 assocs namespaces make continuations sequences hashtables
5 sorting arrays combinators math.bitwise strings system accessors
6 threads splitting io.backend io.windows io.windows.nt.backend
7 io.windows.nt.files io.monitors io.ports io.buffers io.files
8 io.timeouts io windows windows.kernel32 windows.types ;
9 IN: io.windows.nt.monitors
10
11 : open-directory ( path -- handle )
12     normalize-path
13     FILE_LIST_DIRECTORY
14     share-mode
15     f
16     OPEN_EXISTING
17     { FILE_FLAG_BACKUP_SEMANTICS FILE_FLAG_OVERLAPPED } flags
18     f
19     CreateFile opened-file ;
20
21 TUPLE: win32-monitor-port < input-port recursive ;
22
23 TUPLE: win32-monitor < monitor port ;
24
25 : begin-reading-changes ( port -- overlapped )
26     {
27         [ handle>> handle>> ]
28         [ buffer>> ptr>> ]
29         [ buffer>> size>> ]
30         [ recursive>> 1 0 ? ]
31     } cleave
32     FILE_NOTIFY_CHANGE_ALL
33     0 <uint>
34     (make-overlapped)
35     [ f ReadDirectoryChangesW win32-error=0/f ] keep ;
36
37 : read-changes ( port -- bytes-transferred )
38     [
39         [ begin-reading-changes ] [ twiddle-thumbs ] bi
40     ] with-destructors ;
41
42 : parse-action ( action -- changed )
43     {
44         { FILE_ACTION_ADDED [ +add-file+ ] }
45         { FILE_ACTION_REMOVED [ +remove-file+ ] }
46         { FILE_ACTION_MODIFIED [ +modify-file+ ] }
47         { FILE_ACTION_RENAMED_OLD_NAME [ +rename-file+ ] }
48         { FILE_ACTION_RENAMED_NEW_NAME [ +rename-file+ ] }
49         [ drop +modify-file+ ]
50     } case 1array ;
51
52 : memory>u16-string ( alien len -- string )
53     [ memory>byte-array ] keep 2/ c-ushort-array> >string ;
54
55 : parse-notify-record ( buffer -- path changed )
56     [
57         [ FILE_NOTIFY_INFORMATION-FileName ]
58         [ FILE_NOTIFY_INFORMATION-FileNameLength ]
59         bi memory>u16-string
60     ]
61     [ FILE_NOTIFY_INFORMATION-Action parse-action ] bi ;
62
63 : (file-notify-records) ( buffer -- buffer )
64     dup ,
65     dup FILE_NOTIFY_INFORMATION-NextEntryOffset zero? [
66         [ FILE_NOTIFY_INFORMATION-NextEntryOffset ] keep <displaced-alien>
67         (file-notify-records)
68     ] unless ;
69
70 : file-notify-records ( buffer -- seq )
71     [ (file-notify-records) drop ] { } make ;
72
73 :: parse-notify-records ( monitor buffer -- )
74     buffer file-notify-records [
75         parse-notify-record
76         [ monitor path>> prepend-path normalize-path ] dip
77         monitor queue-change
78     ] each ;
79
80 : fill-queue ( monitor -- )
81     dup port>> dup check-disposed
82     [ buffer>> ptr>> ] [ read-changes zero? ] bi
83     [ 2dup parse-notify-records ] unless
84     2drop ;
85
86 : (fill-queue-thread) ( monitor -- )
87     dup fill-queue (fill-queue-thread) ;
88
89 : fill-queue-thread ( monitor -- )
90     [ dup fill-queue (fill-queue-thread) ]
91     [ dup already-disposed? [ 2drop ] [ rethrow ] if ] recover ;
92
93 M:: winnt (monitor) ( path recursive? mailbox -- monitor )
94     [
95         path normalize-path mailbox win32-monitor new-monitor
96             path open-directory \ win32-monitor-port <buffered-port>
97                 recursive? >>recursive
98             >>port
99         dup [ fill-queue-thread ] curry
100         "Windows monitor thread" spawn drop
101     ] with-destructors ;
102
103 M: win32-monitor dispose
104     port>> dispose ;