Skip to content

Instantly share code, notes, and snippets.

@CocoaBeans
Forked from daurnimator/4CF.c
Created July 7, 2016 04:26
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 CocoaBeans/039026acb930d2e8ebeae725e4af8f22 to your computer and use it in GitHub Desktop.
Save CocoaBeans/039026acb930d2e8ebeae725e4af8f22 to your computer and use it in GitHub Desktop.
Use your own main loop on OSX
#include <mach/port.h> /* mach_port_t */
#include <mach/mach.h> /* mach_port_allocate(), mach_task_self(), mach_port_insert_member() */
#include <sys/event.h> /* kqueue(), kevent64(), struct kevent64_s, EVFILT_MACHPORT, EV_SET64, EV_ADD */
#include <sys/time.h> /* struct timespec */
//#include <dispatch/private.h>
extern mach_port_t _dispatch_get_main_queue_port_4CF(void);
extern void _dispatch_main_queue_callback_4CF(void);
#include <stdio.h>
#include <errno.h>
#include <unistd.h> /* close() */
#include <dispatch/dispatch.h>
int main() {
int fd;
struct kevent64_s event;
int n;
if (-1 == (fd = kqueue()))
return (perror("kqueue"), 1);
/* TODO: set cloexec */
mach_port_t x = _dispatch_get_main_queue_port_4CF();
printf("PORT 4CF=%d\n", x);
/* EVFILT_MACHPORT does not allow ports; only portsets */
mach_port_t y;
if (KERN_SUCCESS != mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &y))
return 1;
printf("PORT SET=%d\n", y);
EV_SET64(&event, y, EVFILT_MACHPORT, EV_ADD|EV_CLEAR, MACH_RCV_MSG, 0, 0, 0, 0);
if (0 != kevent64(fd, &event, 1, NULL, 0, 0, &(struct timespec){0,0}))
return (perror("kevent"), 1);
/* XXX: a port can only belong to one portset at once. this needs additional hackery when in a CF-using application */
if (KERN_SUCCESS != mach_port_insert_member(mach_task_self(), x, y))
return 1;
/* say hello */
dispatch_async(
dispatch_get_main_queue(),
^{
printf("hello\n");
}
);
/* in 2 seconds say hello again. */
dispatch_after(
dispatch_time(DISPATCH_TIME_NOW, 2LL*NSEC_PER_SEC),
dispatch_get_main_queue(),
^{
printf("hello from timer\n");
}
);
while (1) {
/* You could poll/select on `fd` now. instead, I'm just going to use a blocking kevent call. */
if (-1 == (n = kevent64(fd, NULL, 0, &event, 1, 0, NULL)))
return (perror("kevent"), 1);
if (n) {
printf("GOT EVENT. ident=%llu filter=%d\n",
event.ident, event.filter);
_dispatch_main_queue_callback_4CF();
} else
return 2;
}
close(fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment