Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Use a dispatch queue instead of the main CFRunLoop
- permits use of Syphon in processes without a main CFRunLoop (such as XPC services)
- receipt of messages is no longer interrupted by eg UI activity
  • Loading branch information
bangnoise committed Apr 4, 2020
1 parent c404f3c commit 9c42b33
Showing 1 changed file with 36 additions and 8 deletions.
44 changes: 36 additions & 8 deletions SyphonCFMessageReceiver.m
Expand Up @@ -31,6 +31,9 @@
#import "SyphonMessaging.h"
#import <libkern/OSAtomic.h>

static dispatch_queue_t theQueue = NULL;
static int theCount = 0;

static CFDataRef MessageReturnCallback (
CFMessagePortRef local,
SInt32 msgid,
Expand All @@ -53,7 +56,31 @@ @implementation SyphonCFMessageReceiver
{
@private
CFMessagePortRef _port;
CFRunLoopSourceRef _runLoopSource;
}

+ (dispatch_queue_t)addUser
{
@synchronized(self) {
theCount++;
if (!theQueue)
{
dispatch_queue_attr_t attributes = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INTERACTIVE, -1);
theQueue = dispatch_queue_create("info.v002.syphon.messaging", attributes);
}
}
return theQueue;
}

+ (void)endUser
{
@synchronized(self) {
theCount--;
if (theCount == 0)
{
dispatch_release(theQueue);
theQueue = NULL;
}
}
}

- (id)initForName:(NSString *)name protocol:(NSString *)protocolName handler:(void (^)(id data, uint32_t type))handler
Expand All @@ -71,24 +98,25 @@ - (id)initForName:(NSString *)name protocol:(NSString *)protocolName handler:(vo
[self release];
return nil;
}
_runLoopSource = CFMessagePortCreateRunLoopSource(kCFAllocatorDefault, _port, 0);
// TODO: Think about which run loop we want to be in (current thread, our own private, main, or what?)
CFRunLoopAddSource(CFRunLoopGetMain(), _runLoopSource, kCFRunLoopCommonModes);
CFMessagePortSetDispatchQueue(_port, [[self class] addUser]);
}
return self;
}

- (void)dealloc
{
if (_runLoopSource) CFRelease(_runLoopSource);
if (_port) CFRelease(_port);
[super dealloc];
}

- (void)invalidate
{
if (_port) CFMessagePortInvalidate(_port);
if (_runLoopSource) CFRunLoopSourceInvalidate(_runLoopSource);
[super invalidate];
if (_port)
{
CFMessagePortInvalidate(_port);
// we only called addUser if _port was created
[[self class] endUser];
}
[super invalidate];
}
@end

0 comments on commit 9c42b33

Please sign in to comment.