Skip to content

Instantly share code, notes, and snippets.

@indutny
Created September 10, 2012 20:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save indutny/fe2f89cf477671135a76 to your computer and use it in GitHub Desktop.
Save indutny/fe2f89cf477671135a76 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/event.h>
#include <mach/task.h>
#include <mach/mach_init.h>
#include <mach/mach_port.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CoreServices/CoreServices.h>
typedef struct __CFRuntimeBase {
uintptr_t _cfisa;
uint8_t _cfinfo[4];
#if __LP64__
uint32_t _rc;
#endif
} CFRuntimeBase;
typedef struct __CFRunLoopMode *CFRunLoopModeRef;
struct __CFRunLoopMode {
CFRuntimeBase _base;
int32_t _lock;
CFStringRef _name;
char _stopped;
char _padding[3];
void* _sources;
void* _observers;
void* _timers;
void* _portToV1SourceMap;
void* _submodes;
mach_port_t _portSet;
signed long _observerMask;
int _kq;
};
struct __CFRunLoop {
CFRuntimeBase _base;
int32_t _lock;
mach_port_t _wakeUpPort;
volatile uint32_t *_stopped;
pthread_t _pthread;
CFMutableSetRef _commonModes;
CFMutableSetRef _commonModeItems;
CFRunLoopModeRef _currentMode;
CFMutableSetRef _modes;
void* _blocks_head;
void* _blocks_tail;
void* _counterpart;
};
void queue_cfloop(int kq, CFRunLoopRef lp, CFStringRef mode_str) {
int mode_cnt;
int i;
int r;
CFRunLoopModeRef modes;
struct kevent event;
mode_cnt = (int) CFSetGetCount(lp->_modes);
modes = (CFRunLoopModeRef) malloc(sizeof(*modes) * mode_cnt);
if (modes == NULL) abort();
CFSetGetValues(lp->_modes, (const void**) &modes);
for (i = 0; i < mode_cnt; i++) {
if (CFStringCompare(modes[i]._name, mode_str, 0) != 0) continue;
if (modes[i]._portSet != 0) {
/* Queue port */
EV_SET(&event,
modes[i]._portSet,
EVFILT_MACHPORT,
EV_ADD | EV_ENABLE,
0,
0,
lp);
r = kevent(kq, &event, 1, NULL, 0, NULL);
assert(r == 0);
}
}
}
void fsevents_cb(ConstFSEventStreamRef streamRef,
void* info,
size_t numEvents,
void* eventPaths,
const FSEventStreamEventFlags eventFlags[],
const FSEventStreamEventId eventIds[]) {
fprintf(stdout, "cb!\n");
}
void schedule_fsevents(CFRunLoopRef loop) {
FSEventStreamContext ctx;
FSEventStreamRef ref;
CFStringRef path;
CFArrayRef paths;
CFAbsoluteTime latency;
FSEventStreamCreateFlags flags;
/* Initialize context */
ctx.version = 0;
ctx.info = NULL;
ctx.retain = NULL;
ctx.release = NULL;
ctx.copyDescription = NULL;
/* Initialize paths array */
path = CFStringCreateWithCString(NULL,
"/private/tmp",
CFStringGetSystemEncoding());
paths = CFArrayCreate(NULL, (const void**)&path, 1, NULL);
latency = 0.15;
/* Set appropriate flags */
flags = kFSEventStreamCreateFlagNone;
ref = FSEventStreamCreate(NULL,
fsevents_cb,
&ctx,
paths,
kFSEventStreamEventIdSinceNow,
latency,
flags);
FSEventStreamScheduleWithRunLoop(ref, loop, kCFRunLoopDefaultMode);
FSEventStreamStart(ref);
}
int main() {
int kq;
int r;
struct kevent events[10];
kq = kqueue();
queue_cfloop(kq, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
schedule_fsevents(CFRunLoopGetCurrent());
while (true) {
fprintf(stdout, "wait\n");
r = kevent(kq, NULL, 0, events, 10, NULL);
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false);
}
close(kq);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment