Search code examples
objective-ccocoamacosgrand-central-dispatch

GCD and RunLoops


In my app I add an CFMachPortRef (via CFMachPortCreateRunLoopSource) to a threads CFRunLoop

Now i was asking myself, can this be done using GCD? Let's say instead of spawning my own NSThread and add the created CFRunLoopSourceRef to its run loop via CFRunLoopAddSource, add the event port to a dispatch's runloop?

I think this will most likely not work due to the inner workings of GCD, but I really don't know.

Update


I got this so far, however neither the callback function for the event tap nor the dispatch_source_event_handler block is called. Any ideas?

CFMachPortRef port = CGEventTapCreate(kCGSessionEventTap,
                                      kCGHeadInsertEventTap,
                                      opts,
                                      desc_.eventMask,
                                      _CGEventCallback,
                                      self);

// create dispatch source
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV,
                                                  CFMachPortGetPort(port),
                                                  0,
                                                  dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));

// set event handler
dispatch_source_set_event_handler(source, ^{
    printf("handle me!\n");
});

dispatch_resume(source);

Solution

  • You can actually use GCD to monitor a Mach port, using the dispatch_source_create() function. The code would look something like this:

    mach_port_t myPort; //assume you have this already
    dispatch_source_t portSource;
    
    portSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, myPort, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT));
    dispatch_source_set_event_handler(portSource, ^(void) { //code for handling incoming message here });
    
    dispatch_resume(portSource);
    

    Whenever a message comes into the port, the block you pass in as the event handler should get called, and you can handle the message there. This example just uses the global queue provided by GCD to handle the message, but you can create a custom queue if you'd like.