Mac OS X monitors work in progress

db4
Slava Pestov 2008-02-12 02:21:47 -06:00
parent ffcc11559f
commit e64089fd0a
10 changed files with 288 additions and 28 deletions

View File

@ -1,35 +1,45 @@
! Copyright (C) 2006 Slava Pestov
! Copyright (C) 2006, 2008 Slava Pestov
! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.c-types alien.syntax kernel math sequences ;
IN: core-foundation
TYPEDEF: void* CFAllocatorRef
TYPEDEF: void* CFArrayRef
TYPEDEF: void* CFBundleRef
TYPEDEF: void* CFStringRef
TYPEDEF: void* CFURLRef
TYPEDEF: void* CFUUIDRef
TYPEDEF: void* CFRunLoopRef
TYPEDEF: bool Boolean
TYPEDEF: int CFIndex
TYPEDEF: double CFTimeInterval
TYPEDEF: double CFAbsoluteTime
FUNCTION: void* CFArrayCreateMutable ( void* allocator, CFIndex capacity, void* callbacks ) ;
FUNCTION: CFArrayRef CFArrayCreateMutable ( CFAllocatorRef allocator, CFIndex capacity, void* callbacks ) ;
FUNCTION: void* CFArrayGetValueAtIndex ( void* array, CFIndex idx ) ;
FUNCTION: void* CFArrayGetValueAtIndex ( CFArrayRef array, CFIndex idx ) ;
FUNCTION: void CFArraySetValueAtIndex ( void* array, CFIndex index, void* value ) ;
FUNCTION: void CFArraySetValueAtIndex ( CFArrayRef array, CFIndex index, void* value ) ;
FUNCTION: CFIndex CFArrayGetCount ( void* array ) ;
FUNCTION: CFIndex CFArrayGetCount ( CFArrayRef array ) ;
: kCFURLPOSIXPathStyle 0 ;
FUNCTION: void* CFURLCreateWithFileSystemPath ( void* allocator, void* filePath, int pathStyle, bool isDirectory ) ;
FUNCTION: CFURLRef CFURLCreateWithFileSystemPath ( CFAllocatorRef allocator, CFStringRef filePath, int pathStyle, Boolean isDirectory ) ;
FUNCTION: void* CFURLCreateWithString ( void* allocator, void* string, void* base ) ;
FUNCTION: CFURLRef CFURLCreateWithString ( CFAllocatorRef allocator, CFStringRef string, CFURLRef base ) ;
FUNCTION: void* CFURLCopyFileSystemPath ( void* url, int pathStyle ) ;
FUNCTION: CFURLRef CFURLCopyFileSystemPath ( CFURLRef url, int pathStyle ) ;
FUNCTION: void* CFStringCreateWithCharacters ( void* allocator, ushort* cStr, CFIndex numChars ) ;
FUNCTION: CFStringRef CFStringCreateWithCharacters ( CFAllocatorRef allocator, ushort* cStr, CFIndex numChars ) ;
FUNCTION: CFIndex CFStringGetLength ( void* theString ) ;
FUNCTION: CFIndex CFStringGetLength ( CFStringRef theString ) ;
FUNCTION: void CFStringGetCharacters ( void* theString, CFIndex start, CFIndex length, void* buffer ) ;
FUNCTION: void* CFBundleCreate ( void* allocator, void* bundleURL ) ;
FUNCTION: CFBundleRef CFBundleCreate ( CFAllocatorRef allocator, CFURLRef bundleURL ) ;
FUNCTION: bool CFBundleLoadExecutable ( void* bundle ) ;
FUNCTION: Boolean CFBundleLoadExecutable ( CFBundleRef bundle ) ;
FUNCTION: void CFRelease ( void* cf ) ;
@ -52,6 +62,9 @@ FUNCTION: void CFRelease ( void* cf ) ;
: CF>string-array ( alien -- seq )
CF>array [ CF>string ] map ;
: <CFStringArray> ( seq -- alien )
[ <CFString> ] map dup <CFArray> swap [ CFRelease ] each ;
: <CFFileSystemURL> ( string dir? -- url )
>r <CFString> f over kCFURLPOSIXPathStyle
r> CFURLCreateWithFileSystemPath swap CFRelease ;
@ -72,3 +85,5 @@ FUNCTION: void CFRelease ( void* cf ) ;
] [
"Cannot load bundled named " swap append throw
] ?if ;
FUNCTION: CFRunLoopRef CFRunLoopGetMain ( ) ;

View File

@ -0,0 +1,203 @@
! Copyright (C) 2008 Slava Pestov
! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.c-types alien.syntax kernel math sequences
namespaces assocs init continuations ;
IN: core-foundation
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
! FSEventStream API, Leopard only !
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
: kFSEventStreamCreateFlagUseCFTypes 2 ; inline
: kFSEventStreamCreateFlagWatchRoot 4 ; inline
: kFSEventStreamEventFlagMustScanSubDirs 1 ; inline
: kFSEventStreamEventFlagUserDropped 2 ; inline
: kFSEventStreamEventFlagKernelDropped 4 ; inline
: kFSEventStreamEventFlagEventIdsWrapped 8 ; inline
: kFSEventStreamEventFlagHistoryDone 16 ; inline
: kFSEventStreamEventFlagRootChanged 32 ; inline
: kFSEventStreamEventFlagMount 64 ; inline
: kFSEventStreamEventFlagUnmount 128 ; inline
TYPEDEF: int FSEventStreamCreateFlags
TYPEDEF: int FSEventStreamEventFlags
TYPEDEF: longlong FSEventStreamEventId
TYPEDEF: void* FSEventStreamRef
C-STRUCT: FSEventStreamContext
{ "CFIndex" "version" }
{ "void*" "info" }
{ "void*" "retain" }
{ "void*" "release" }
{ "void*" "copyDescription" } ;
! callback(FSEventStreamRef streamRef, void *clientCallBackInfo, size_t numEvents, void *eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]);
TYPEDEF: void* FSEventStreamCallback
: FSEventStreamEventIdSinceNow HEX: FFFFFFFFFFFFFFFF ; inline
FUNCTION: FSEventStreamRef FSEventStreamCreate (
CFAllocatorRef allocator,
FSEventStreamCallback callback,
FSEventStreamContext* context,
CFArrayRef pathsToWatch,
FSEventStreamEventId sinceWhen,
CFTimeInterval latency,
FSEventStreamCreateFlags flags ) ;
FUNCTION: FSEventStreamRef FSEventStreamCreateRelativeToDevice (
CFAllocatorRef allocator,
FSEventStreamCallback callback,
FSEventStreamContext* context,
dev_t deviceToWatch,
CFArrayRef pathsToWatchRelativeToDevice,
FSEventStreamEventId sinceWhen,
CFTimeInterval latency,
FSEventStreamCreateFlags flags ) ;
FUNCTION: FSEventStreamEventId FSEventStreamGetLatestEventId ( FSEventStreamRef streamRef ) ;
FUNCTION: dev_t FSEventStreamGetDeviceBeingWatched ( FSEventStreamRef streamRef ) ;
FUNCTION: CFArrayRef FSEventStreamCopyPathsBeingWatched ( FSEventStreamRef streamRef ) ;
FUNCTION: FSEventStreamEventId FSEventsGetCurrentEventId ( ) ;
FUNCTION: CFUUIDRef FSEventsCopyUUIDForDevice ( dev_t dev ) ;
FUNCTION: FSEventStreamEventId FSEventsGetLastEventIdForDeviceBeforeTime (
dev_t dev,
CFAbsoluteTime time ) ;
FUNCTION: Boolean FSEventsPurgeEventsForDeviceUpToEventId (
dev_t dev,
FSEventStreamEventId eventId ) ;
FUNCTION: void FSEventStreamRetain ( FSEventStreamRef streamRef ) ;
FUNCTION: void FSEventStreamRelease ( FSEventStreamRef streamRef ) ;
FUNCTION: void FSEventStreamScheduleWithRunLoop (
FSEventStreamRef streamRef,
CFRunLoopRef runLoop,
CFStringRef runLoopMode ) ;
FUNCTION: void FSEventStreamUnscheduleFromRunLoop (
FSEventStreamRef streamRef,
CFRunLoopRef runLoop,
CFStringRef runLoopMode ) ;
FUNCTION: void FSEventStreamInvalidate ( FSEventStreamRef streamRef ) ;
FUNCTION: Boolean FSEventStreamStart ( FSEventStreamRef streamRef ) ;
FUNCTION: FSEventStreamEventId FSEventStreamFlushAsync ( FSEventStreamRef streamRef ) ;
FUNCTION: void FSEventStreamFlushSync ( FSEventStreamRef streamRef ) ;
FUNCTION: void FSEventStreamStop ( FSEventStreamRef streamRef ) ;
FUNCTION: void FSEventStreamShow ( FSEventStreamRef streamRef ) ;
FUNCTION: CFStringRef FSEventStreamCopyDescription ( FSEventStreamRef streamRef ) ;
: make-FSEventStreamContext ( info -- alien )
"FSEventStreamContext" <c-object>
[ set-FSEventStreamContext-info ] keep ;
: <FSEventStream> ( callback info paths latency flags -- event-stream )
>r >r >r >r >r
f ! allocator
r> ! callback
r> make-FSEventStreamContext
r> <CFStringArray> ! paths
FSEventStreamEventIdSinceNow ! sinceWhen
r> ! latency
r> ! flags
FSEventStreamCreate ;
: kCFRunLoopCommonModes ( -- string )
"kCFRunLoopCommonModes" f dlsym *void* ;
: schedule-event-stream ( event-stream -- )
CFRunLoopGetMain
kCFRunLoopCommonModes
FSEventStreamScheduleWithRunLoop ;
: unschedule-event-stream ( event-stream -- )
CFRunLoopGetMain
kCFRunLoopCommonModes
FSEventStreamUnscheduleFromRunLoop ;
: enable-event-stream ( event-stream -- )
dup
schedule-event-stream
dup FSEventStreamStart [
drop
] [
dup unschedule-event-stream
FSEventStreamRelease
"Cannot enable FSEventStream" throw
] if ;
: disable-event-stream ( event-stream -- )
dup FSEventStreamStop
unschedule-event-stream ;
SYMBOL: event-stream-callbacks
: event-stream-counter \ event-stream-counter counter ;
[
H{ } clone event-stream-callbacks set-global
1 \ event-stream-counter set-global
] "core-foundation" add-init-hook
event-stream-callbacks global [ H{ } assoc-like ] change-at
: add-event-source-callback ( quot -- id )
event-stream-counter <alien>
[ event-stream-callbacks get set-at ] keep ;
: remove-event-source-callback ( id -- )
event-stream-callbacks get delete-at ;
: >event-triple ( n eventPaths eventFlags eventIds -- triple )
[
>r >r >r dup dup
r> char*-nth ,
r> int-nth ,
r> longlong-nth ,
] { } make ;
: master-event-source-callback ( -- alien )
"void"
{
"FSEventStreamRef"
"void*" ! info
"size_t" ! numEvents
"void*" ! eventPaths
"FSEventStreamEventFlags*"
"FSEventStreamEventId*"
}
"cdecl" [
[ >event-triple ] 3curry map
swap event-stream-callbacks get at call
drop
] alien-callback ;
TUPLE: event-stream info handle ;
: <event-stream> ( quot paths latency flags -- event-stream )
>r >r >r
add-event-source-callback dup
>r master-event-source-callback r>
r> r> r> <FSEventStream>
dup enable-event-stream
event-stream construct-boa ;
M: event-stream dispose
dup event-stream-info remove-event-source-callback
event-stream-handle dup disable-event-stream
FSEventStreamRelease ;

View File

@ -5,14 +5,14 @@ USING: io.backend io.unix.backend io.unix.kqueue io.unix.select
io.launcher io.unix.launcher namespaces kernel assocs threads
continuations ;
! On *BSD and Mac OS X, we use select() for the top-level
! multiplexer, and we hang a kqueue off of it but file change
! notification and process exit notification.
! On Mac OS X, we use select() for the top-level
! multiplexer, and we hang a kqueue off of it for process exit
! notification.
! kqueue is buggy with files and ptys so we can't use it as the
! main multiplexer.
TUPLE: bsd-io ;
MIXIN: bsd-io
INSTANCE: bsd-io unix-io
@ -25,5 +25,3 @@ M: bsd-io init-io ( -- )
M: bsd-io register-process ( process -- )
process-handle kqueue-mx get-global add-pid-task ;
T{ bsd-io } set-io-backend

View File

@ -0,0 +1,8 @@
IN: io.unix.freebsd
USING: io.unix.bsd io.backend core-foundation.fsevents ;
TUPLE: freebsd-io ;
INSTANCE: freebsd-io bsd-io
T{ freebsd-io } set-io-backend

View File

@ -136,5 +136,3 @@ M: linux-io init-io ( -- )
T{ linux-io } set-io-backend
[ start-wait-thread ] "io.unix.linux" add-init-hook
"vocabs.monitor" require

View File

@ -0,0 +1,27 @@
IN: io.unix.macosx
USING: io.unix.bsd io.backend io.monitors io.monitors.private
continuations kernel core-foundation.fsevents ;
TUPLE: macosx-io ;
INSTANCE: macosx-io bsd-io
T{ macosx-io } set-io-backend
TUPLE: macosx-monitor ;
: enqueue-notifications ( triples monitor -- )
monitor-queue [
[ first { +modify-file+ } swap changed-file ] each
] bind ;
M: macosx-io <monitor>
drop
f macosx-monitor construct-simple-monitor
dup [ enqueue-notifications ] curry
rot 1array 0 0 <event-stream>
over set-simple-monitor-handle ;
M: macosx-monitor dispose
dup simple-monitor-handle dispose delegate dispose ;

View File

@ -0,0 +1,8 @@
IN: io.unix.netbsd
USING: io.unix.bsd io.backend ;
TUPLE: netbsd-io ;
INSTANCE: netbsd-io bsd-io
T{ netbsd-io } set-io-backend

View File

@ -0,0 +1,8 @@
IN: io.unix.openbsd
USING: io.unix.bsd io.backend core-foundation.fsevents ;
TUPLE: openbsd-io ;
INSTANCE: openbsd-io bsd-io
T{ openbsd-io } set-io-backend

View File

@ -2,9 +2,6 @@ USING: io.unix.backend io.unix.files io.unix.sockets io.timeouts
io.unix.launcher io.unix.mmap io.backend combinators namespaces
system vocabs.loader ;
{
{ [ bsd? ] [ "io.unix.bsd" ] }
{ [ macosx? ] [ "io.unix.bsd" ] }
{ [ linux? ] [ "io.unix.linux" ] }
{ [ solaris? ] [ "io.unix.solaris" ] }
} cond require
"io.unix." os append require
"vocabs.monitor" require

View File

@ -12,5 +12,3 @@ USE: io.windows.mmap
USE: io.backend
T{ windows-nt-io } set-io-backend
"vocabs.monitor" require