Commit 16c3ae28 authored by Pierre d'Herbemont's avatar Pierre d'Herbemont

VLCEventManager.m: Support event collapsing.

parent d8c43b46
......@@ -31,7 +31,8 @@ static VLCEventManager * defaultManager = NULL;
enum message_type_t
{
VLCNotification,
VLCObjectMethodWithObjectArg
VLCObjectMethodWithObjectArg,
VLCObjectMethodWithArrayArg
};
struct message {
......@@ -57,7 +58,7 @@ struct message {
static void * EventDispatcherMainLoop(void * user_data)
{
VLCEventManager * self = user_data;
for(;;)
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
......@@ -65,14 +66,20 @@ static void * EventDispatcherMainLoop(void * user_data)
NSData *dataMessage;
int i;
/* Sleep a bit not to flood the interface */
msleep(300);
/* Wait for some data */
pthread_mutex_lock( [self queueLock] );
/* Wait until we have something on the queue */
while([[self messageQueue] count] <= 0 )
{
pthread_cond_wait( [self signalData], [self queueLock] );
}
//if( [[self messageQueue] count] % 100 == 0 || [[self messageQueue] count] < 100 )
// NSLog(@"[EVENT_MANAGER] On the stack we have %d elements", [[self messageQueue] count]);
message = (struct message *)[(NSData *)[[self messageQueue] lastObject] bytes];
/* Don't send the same notification twice */
......@@ -81,27 +88,60 @@ static void * EventDispatcherMainLoop(void * user_data)
for( i = 0; i < [[self messageQueue] count]-1; i++ )
{
message_newer = (struct message *)[(NSData *)[[self messageQueue] objectAtIndex: i] bytes];
if( message_newer->type != VLCNotification )
continue;
if( message_newer->target == message->target && message_newer->target == message->target && [message_newer->u.name isEqualToString:message->u.name] )
if( message_newer->type == VLCNotification &&
message_newer->target == message->target &&
[message_newer->u.name isEqualToString:message->u.name] )
{
[message_newer->target release];
[message->u.name release];
[[self messageQueue] removeObjectAtIndex: i];
i--;
continue;
}
}
}
else if( message->type == VLCObjectMethodWithArrayArg )
{
NSMutableArray * newArg = nil;
/* Collapse messages that takes array arg by sending one bigger array */
for( i = [[self messageQueue] count]-2; i >= 0; i-- )
{
message_newer = (struct message *)[(NSData *)[[self messageQueue] objectAtIndex: i] bytes];
if( message_newer->type == VLCObjectMethodWithArrayArg &&
message_newer->target == message->target &&
message_newer->sel == message->sel )
{
if(!newArg)
newArg = [NSMutableArray arrayWithArray: message->u.object];
[newArg addObjectsFromArray: message_newer->u.object];
[message_newer->target release];
[message_newer->u.object release];
[[self messageQueue] removeObjectAtIndex: i];
i++;
continue;
}
/* It should be a good idea not to collapse event, with other kind of event in-between
* Ignore for now only if target is the same */
else if( message_newer->target == message->target )
break;
}
if( newArg )
{
[message->u.object release];
message->u.object = [newArg retain];
[newArg retain];
}
}
dataMessage = [[self messageQueue] lastObject];
pthread_mutex_unlock( [self queueLock] );
if( message->type == VLCNotification )
[self performSelectorOnMainThread:@selector(callDelegateOfObjectAndSendNotificationWithArgs:) withObject:[dataMessage retain] /* released in the call */ waitUntilDone: NO];
else
[self performSelectorOnMainThread:@selector(callObjectMethodWithArgs:) withObject:[dataMessage retain] /* released in the call */ waitUntilDone: NO];
[self performSelectorOnMainThread:@selector(callObjectMethodWithArgs:) withObject:[dataMessage retain] /* released in the call */ waitUntilDone: YES];
pthread_mutex_lock( [self queueLock] );
[[self messageQueue] removeLastObject];
......@@ -124,10 +164,21 @@ static void * EventDispatcherMainLoop(void * user_data)
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");
}
pthread_mutex_init( &queueLock, NULL );
pthread_cond_init( &signalData, NULL );
pthread_create( &dispatcherThread, NULL, EventDispatcherMainLoop, self );
......@@ -163,10 +214,10 @@ static void * EventDispatcherMainLoop(void * user_data)
return;
}
pthread_mutex_lock( [self queueLock] );
[[self messageQueue] insertObject:[NSData dataWithBytes:&message length:sizeof(struct message)] atIndex:0];
pthread_cond_signal( [self signalData] );
pthread_mutex_unlock( [self queueLock] );
// pthread_mutex_lock( [self queueLock] );
// [[self messageQueue] insertObject:[NSData dataWithBytes:&message length:sizeof(struct message)] atIndex:0];
// pthread_cond_signal( [self signalData] );
// pthread_mutex_unlock( [self queueLock] );
[pool release];
}
......@@ -179,15 +230,9 @@ static void * EventDispatcherMainLoop(void * user_data)
[aTarget retain],
aSelector,
[arg retain],
VLCObjectMethodWithObjectArg
[arg isKindOfClass:[NSArray class]] ? VLCObjectMethodWithArrayArg : VLCObjectMethodWithObjectArg
};
if([NSThread isMainThread])
{
[self callObjectMethodWithArgs:[[NSData dataWithBytes:&message length:sizeof(struct message)] retain] /* released in the call */];
return;
}
pthread_mutex_lock( [self queueLock] );
[[self messageQueue] insertObject:[NSData dataWithBytes:&message length:sizeof(struct message)] atIndex:0];
pthread_cond_signal( [self signalData] );
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment