|
@@ -83,9 +83,7 @@ typedef enum
|
|
|
- (void)callDelegateOfObject:(id)aTarget withDelegateMethod:(SEL)aSelector withNotificationName:(NSString *)aNotificationName;
|
|
|
- (pthread_cond_t *)signalData;
|
|
|
- (pthread_mutex_t *)queueLock;
|
|
|
-- (NSMutableArray *)messageQueue;
|
|
|
-- (NSMutableArray *)pendingMessagesOnMainThread;
|
|
|
-- (NSLock *)pendingMessagesLock;
|
|
|
+- (void)startEventLoop;
|
|
|
|
|
|
- (void)addMessageToHandleOnMainThread:(message_t *)message;
|
|
|
@end
|
|
@@ -98,7 +96,59 @@ static void * EventDispatcherMainLoop(void * user_data)
|
|
|
{
|
|
|
VLCEventManager * self = (__bridge VLCEventManager *)(user_data);
|
|
|
|
|
|
+ [self startEventLoop];
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+@implementation VLCEventManager
|
|
|
+
|
|
|
++ (id)sharedManager
|
|
|
+{
|
|
|
+ static dispatch_once_t onceToken;
|
|
|
+ static VLCEventManager *defaultManager = nil;
|
|
|
+ dispatch_once(&onceToken, ^{
|
|
|
+ defaultManager = [[VLCEventManager alloc] init];
|
|
|
+ });
|
|
|
+
|
|
|
+ return defaultManager;
|
|
|
+}
|
|
|
+
|
|
|
+- (void)dummy
|
|
|
+{
|
|
|
+ /* Put Cocoa in multithreaded mode by calling a dummy function */
|
|
|
+}
|
|
|
+
|
|
|
+- (id)init
|
|
|
+{
|
|
|
+ if (self = [super init]) {
|
|
|
+ if (![NSThread isMultiThreaded]) {
|
|
|
+ [NSThread detachNewThreadSelector:@selector(dummy) toTarget:self withObject:nil];
|
|
|
+ NSAssert([NSThread isMultiThreaded], @"Can't put Cocoa in multithreaded mode");
|
|
|
+ }
|
|
|
+
|
|
|
+ _messageQueue = [NSMutableArray new];
|
|
|
+ _pendingMessagesOnMainThread = [NSMutableArray new];
|
|
|
+ _pendingMessagesLock = [[NSLock alloc] init];
|
|
|
+
|
|
|
+ pthread_mutex_init(&_queueLock, NULL);
|
|
|
+ pthread_cond_init(&_signalData, NULL);
|
|
|
+ pthread_create(&_dispatcherThread, NULL, EventDispatcherMainLoop, (__bridge void *)(self));
|
|
|
+ }
|
|
|
+ return self;
|
|
|
+}
|
|
|
+
|
|
|
+- (void)dealloc
|
|
|
+{
|
|
|
+ pthread_kill(_dispatcherThread, SIGKILL);
|
|
|
+ pthread_join(_dispatcherThread, NULL);
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark -
|
|
|
+
|
|
|
+- (void)startEventLoop {
|
|
|
for (;;) {
|
|
|
+ @autoreleasepool {
|
|
|
message_t * message, * message_newer = NULL;
|
|
|
|
|
|
/* Sleep a bit not to flood the interface */
|
|
@@ -108,23 +158,23 @@ static void * EventDispatcherMainLoop(void * user_data)
|
|
|
|
|
|
pthread_mutex_lock([self queueLock]);
|
|
|
/* Wait until we have something on the queue */
|
|
|
- while ([[self messageQueue] count] <= 0)
|
|
|
+ while (_messageQueue.count <= 0)
|
|
|
pthread_cond_wait([self signalData], [self queueLock]);
|
|
|
|
|
|
/* Get the first object off the queue. */
|
|
|
- message = [[self messageQueue] lastObject]; // Released in 'call'
|
|
|
- [[self messageQueue] removeLastObject];
|
|
|
+ message = [_messageQueue lastObject]; // Released in 'call'
|
|
|
+ [_messageQueue removeLastObject];
|
|
|
|
|
|
/* Remove duplicate notifications (keep the newest one). */
|
|
|
if (message.type == VLCNotification) {
|
|
|
NSInteger last_match_msg = -1;
|
|
|
- for (NSInteger i = [[self messageQueue] count]-1; i >= 0; i--) {
|
|
|
- message_newer = [self messageQueue][i];
|
|
|
+ for (NSInteger i = _messageQueue.count - 1; i >= 0; i--) {
|
|
|
+ message_newer = _messageQueue[i];
|
|
|
if (message_newer.type == VLCNotification &&
|
|
|
message_newer.target == message.target &&
|
|
|
[message_newer.name isEqualToString:message.name]) {
|
|
|
if (last_match_msg >= 0) {
|
|
|
- [[self messageQueue] removeObjectAtIndex:last_match_msg];
|
|
|
+ [_messageQueue removeObjectAtIndex:last_match_msg];
|
|
|
}
|
|
|
last_match_msg = i;
|
|
|
}
|
|
@@ -138,8 +188,8 @@ static void * EventDispatcherMainLoop(void * user_data)
|
|
|
NSMutableArray * newArg = nil;
|
|
|
|
|
|
/* Collapse messages that takes array arg by sending one bigger array */
|
|
|
- for (NSInteger i = [[self messageQueue] count] - 1; i >= 0; i--) {
|
|
|
- message_newer = [self messageQueue][i];
|
|
|
+ for (NSInteger i = [_messageQueue count] - 1; i >= 0; i--) {
|
|
|
+ message_newer = _messageQueue[i];
|
|
|
if (message_newer.type == VLCObjectMethodWithArrayArg &&
|
|
|
message_newer.target == message.target &&
|
|
|
message_newer.sel == message.sel) {
|
|
@@ -148,7 +198,7 @@ static void * EventDispatcherMainLoop(void * user_data)
|
|
|
}
|
|
|
|
|
|
[newArg addObjectsFromArray:message_newer.object];
|
|
|
- [[self messageQueue] removeObjectAtIndex:i];
|
|
|
+ [_messageQueue removeObjectAtIndex:i];
|
|
|
}
|
|
|
/* It shouldn be a good idea not to collapse event with other kind of event in-between.
|
|
|
* This could be particulary problematic when the same object receive two related events
|
|
@@ -174,49 +224,7 @@ static void * EventDispatcherMainLoop(void * user_data)
|
|
|
withObject:message
|
|
|
waitUntilDone: YES];
|
|
|
}
|
|
|
- return nil;
|
|
|
-}
|
|
|
-
|
|
|
-@implementation VLCEventManager
|
|
|
-+ (id)sharedManager
|
|
|
-{
|
|
|
- static dispatch_once_t onceToken;
|
|
|
- static VLCEventManager *defaultManager = nil;
|
|
|
- dispatch_once(&onceToken, ^{
|
|
|
- defaultManager = [[VLCEventManager alloc] init];
|
|
|
- });
|
|
|
-
|
|
|
- return defaultManager;
|
|
|
-}
|
|
|
-
|
|
|
-- (void)dummy
|
|
|
-{
|
|
|
- /* Put Cocoa in multithreaded mode by calling a dummy function */
|
|
|
-}
|
|
|
-
|
|
|
-- (id)init
|
|
|
-{
|
|
|
- if (self = [super init]) {
|
|
|
- if (![NSThread isMultiThreaded]) {
|
|
|
- [NSThread detachNewThreadSelector:@selector(dummy) toTarget:self withObject:nil];
|
|
|
- NSAssert([NSThread isMultiThreaded], @"Can't put Cocoa in multithreaded mode");
|
|
|
- }
|
|
|
-
|
|
|
- _messageQueue = [NSMutableArray new];
|
|
|
- _pendingMessagesOnMainThread = [NSMutableArray new];
|
|
|
- _pendingMessagesLock = [[NSLock alloc] init];
|
|
|
-
|
|
|
- pthread_mutex_init(&_queueLock, NULL);
|
|
|
- pthread_cond_init(&_signalData, NULL);
|
|
|
- pthread_create(&_dispatcherThread, NULL, EventDispatcherMainLoop, (__bridge void *)(self));
|
|
|
}
|
|
|
- return self;
|
|
|
-}
|
|
|
-
|
|
|
-- (void)dealloc
|
|
|
-{
|
|
|
- pthread_kill(_dispatcherThread, SIGKILL);
|
|
|
- pthread_join(_dispatcherThread, NULL);
|
|
|
}
|
|
|
|
|
|
- (void)callOnMainThreadDelegateOfObject:(id)aTarget withDelegateMethod:(SEL)aSelector withNotificationName:(NSString *)aNotificationName
|
|
@@ -230,7 +238,7 @@ static void * EventDispatcherMainLoop(void * user_data)
|
|
|
message.type = VLCNotification;
|
|
|
|
|
|
pthread_mutex_lock([self queueLock]);
|
|
|
- [[self messageQueue] insertObject:message atIndex:0];
|
|
|
+ [_messageQueue insertObject:message atIndex:0];
|
|
|
pthread_cond_signal([self signalData]);
|
|
|
pthread_mutex_unlock([self queueLock]);
|
|
|
}
|
|
@@ -246,7 +254,7 @@ static void * EventDispatcherMainLoop(void * user_data)
|
|
|
message.type = [arg isKindOfClass:[NSArray class]] ? VLCObjectMethodWithArrayArg : VLCObjectMethodWithObjectArg;
|
|
|
|
|
|
pthread_mutex_lock([self queueLock]);
|
|
|
- [[self messageQueue] insertObject:message atIndex:0];
|
|
|
+ [_messageQueue insertObject:message atIndex:0];
|
|
|
pthread_cond_signal([self signalData]);
|
|
|
pthread_mutex_unlock([self queueLock]);
|
|
|
}
|
|
@@ -254,16 +262,14 @@ static void * EventDispatcherMainLoop(void * user_data)
|
|
|
|
|
|
- (void)cancelCallToObject:(id)target
|
|
|
{
|
|
|
-
|
|
|
// Remove all queued message
|
|
|
pthread_mutex_lock([self queueLock]);
|
|
|
[_pendingMessagesLock lock];
|
|
|
|
|
|
- NSMutableArray *queue = [self messageQueue];
|
|
|
- for (NSInteger i = [queue count] - 1; i >= 0; i--) {
|
|
|
- message_t *message = (message_t *)queue[i];
|
|
|
+ for (NSInteger i = _messageQueue.count - 1; i >= 0; i--) {
|
|
|
+ message_t *message = _messageQueue[i];
|
|
|
if (message.target == target)
|
|
|
- [queue removeObjectAtIndex:i];
|
|
|
+ [_messageQueue removeObjectAtIndex:i];
|
|
|
}
|
|
|
|
|
|
// Remove all pending messages
|
|
@@ -329,22 +335,6 @@ static void * EventDispatcherMainLoop(void * user_data)
|
|
|
method(delegate, aSelector, [NSNotification notificationWithName:aNotificationName object:aTarget]);
|
|
|
}
|
|
|
|
|
|
-- (NSMutableArray *)messageQueue
|
|
|
-{
|
|
|
- return _messageQueue;
|
|
|
-}
|
|
|
-
|
|
|
-- (NSMutableArray *)pendingMessagesOnMainThread
|
|
|
-{
|
|
|
- return _pendingMessagesOnMainThread;
|
|
|
-}
|
|
|
-
|
|
|
-- (NSLock *)pendingMessagesLock
|
|
|
-{
|
|
|
- return _pendingMessagesLock;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
- (pthread_cond_t *)signalData
|
|
|
{
|
|
|
return &_signalData;
|