Commit 146cc65c authored by Faustino Osuna's avatar Faustino Osuna

MacOSX/Framework/VLCEventManager: Code clean up/documentation. Standardized...

MacOSX/Framework/VLCEventManager: Code clean up/documentation.  Standardized the way duplicate notifications are consolidated.
parent 1f540b87
......@@ -26,35 +26,43 @@
#import "VLCEventManager.h"
#import <pthread.h>
static VLCEventManager * defaultManager = NULL;
enum message_type_t
/**
* Defines the type of interthread message on the queue.
*/
typedef enum
{
VLCNotification,
VLCObjectMethodWithObjectArg,
VLCObjectMethodWithArrayArg
};
struct message {
id target;
SEL sel;
union u
VLCNotification, //< Standard NSNotification.
VLCObjectMethodWithObjectArg, //< Method with an object argument.
VLCObjectMethodWithArrayArg //< Method with an array argument.
} message_type_t;
/**
* Data structured used to enqueue messages onto the queue.
*/
typedef struct {
id target; //< Target object that should receive the message (retained until method is called).
SEL sel; //< A selector that identifies the message to be sent to the target.
union u //< Object could either be a VLCNotification or other.
{
NSString * name;
id object;
NSString * name; //< Name to be used for NSNotification
id object; //< Object argument to pass to the target via the selector.
} u;
enum message_type_t type;
};
message_type_t type; //< Type of queued message.
} message_t;
@interface VLCEventManager (Private)
- (void)callDelegateOfObjectAndSendNotificationWithArgs:(NSData*)data;
- (void)callObjectMethodWithArgs:(NSData*)data;
- (void)callDelegateOfObject:(id) aTarget withDelegateMethod:(SEL)aSelector withNotificationName: (NSString *)aNotificationName;
- (void)callDelegateOfObject:(id) aTarget withDelegateMethod:(SEL)aSelector withNotificationName:(NSString *)aNotificationName;
- (pthread_cond_t *)signalData;
- (pthread_mutex_t *)queueLock;
- (NSMutableArray *)messageQueue;
@end
/**
* Provides a function for the main entry point for the dispatch thread. It dispatches any messages that is queued.
* \param user_data Pointer to the VLCEventManager instance that instiated this thread.
*/
static void * EventDispatcherMainLoop(void * user_data)
{
VLCEventManager * self = user_data;
......@@ -62,7 +70,7 @@ static void * EventDispatcherMainLoop(void * user_data)
for(;;)
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
struct message * message, * message_newer = NULL;
message_t * message, * message_newer = NULL;
NSData * dataMessage;
int i;
......@@ -81,14 +89,17 @@ static void * EventDispatcherMainLoop(void * user_data)
//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];
/* Get the first object off the queue. */
dataMessage = [[[self messageQueue] lastObject] retain]; // Released in 'call'
[[self messageQueue] removeLastObject];
message = (message_t *)[dataMessage bytes];
/* Don't send the same notification twice */
/* Remove duplicate notifications. */
if( message->type == VLCNotification )
{
for( i = 0; i < [[self messageQueue] count]-1; i++ )
for( i = [[self messageQueue] count]-1; i >= 0; i-- )
{
message_newer = (struct message *)[(NSData *)[[self messageQueue] objectAtIndex:i] bytes];
message_newer = (message_t *)[(NSData *)[[self messageQueue] objectAtIndex:i] bytes];
if( message_newer->type == VLCNotification &&
message_newer->target == message->target &&
[message_newer->u.name isEqualToString:message->u.name] )
......@@ -96,56 +107,53 @@ static void * EventDispatcherMainLoop(void * user_data)
[message_newer->target release];
[message_newer->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-- )
for( i = [[self messageQueue] count]-1; i >= 0; i-- )
{
message_newer = (struct message *)[(NSData *)[[self messageQueue] objectAtIndex: i] bytes];
message_newer = (message_t *)[(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];
[message->u.object release];
}
[newArg addObjectsFromArray:message_newer->u.object];
[message_newer->target release];
[message_newer->u.object release];
[[self messageQueue] removeObjectAtIndex: i];
continue;
[[self messageQueue] removeObjectAtIndex:i];
}
/* 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 )
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];
[self performSelectorOnMainThread:@selector(callDelegateOfObjectAndSendNotificationWithArgs:)
withObject:dataMessage
waitUntilDone: NO];
else
[self performSelectorOnMainThread:@selector(callObjectMethodWithArgs:) withObject:[dataMessage retain] /* released in the call */ waitUntilDone: YES];
[self performSelectorOnMainThread:@selector(callObjectMethodWithArgs:)
withObject:dataMessage
waitUntilDone: YES];
pthread_mutex_lock( [self queueLock] );
[[self messageQueue] removeLastObject];
pthread_mutex_unlock( [self queueLock] );
[pool release];
}
return nil;
......@@ -154,6 +162,8 @@ static void * EventDispatcherMainLoop(void * user_data)
@implementation VLCEventManager
+ (id)sharedManager
{
static VLCEventManager * defaultManager = NULL;
/* We do want a lock here to avoid leaks */
if ( !defaultManager )
{
......@@ -197,9 +207,9 @@ static void * EventDispatcherMainLoop(void * user_data)
- (void)callOnMainThreadDelegateOfObject:(id)aTarget withDelegateMethod:(SEL)aSelector withNotificationName: (NSString *)aNotificationName
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
struct message message =
message_t message =
{
[aTarget retain],
aSelector,
......@@ -207,16 +217,17 @@ static void * EventDispatcherMainLoop(void * user_data)
VLCNotification
};
if([NSThread isMainThread])
{
[self callDelegateOfObjectAndSendNotificationWithArgs:[[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] );
// pthread_mutex_unlock( [self queueLock] );
// if( [NSThread isMainThread] )
// {
[self callDelegateOfObjectAndSendNotificationWithArgs:[[NSData dataWithBytes:&message length:sizeof(message_t)] retain] /* released in the call */];
// }
// else
// {
// pthread_mutex_lock( [self queueLock] );
// [[self messageQueue] insertObject:[NSData dataWithBytes:&message length:sizeof(message_t)] atIndex:0];
// pthread_cond_signal( [self signalData] );
// pthread_mutex_unlock( [self queueLock] );
// }
[pool release];
}
......@@ -224,7 +235,7 @@ static void * EventDispatcherMainLoop(void * user_data)
- (void)callOnMainThreadObject:(id)aTarget withMethod:(SEL)aSelector withArgumentAsObject: (id)arg
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
struct message message =
message_t message =
{
[aTarget retain],
aSelector,
......@@ -233,7 +244,7 @@ static void * EventDispatcherMainLoop(void * user_data)
};
pthread_mutex_lock( [self queueLock] );
[[self messageQueue] insertObject:[NSData dataWithBytes:&message length:sizeof(struct message)] atIndex:0];
[[self messageQueue] insertObject:[NSData dataWithBytes:&message length:sizeof(message_t)] atIndex:0];
pthread_cond_signal( [self signalData] );
pthread_mutex_unlock( [self queueLock] );
......@@ -244,7 +255,7 @@ static void * EventDispatcherMainLoop(void * user_data)
@implementation VLCEventManager (Private)
- (void)callDelegateOfObjectAndSendNotificationWithArgs:(NSData*)data
{
struct message * message = (struct message *)[data bytes];
message_t * message = (message_t *)[data bytes];
[self callDelegateOfObject:message->target withDelegateMethod:message->sel withNotificationName:message->u.name];
[message->u.name release];
......@@ -254,7 +265,7 @@ static void * EventDispatcherMainLoop(void * user_data)
- (void)callObjectMethodWithArgs:(NSData*)data
{
struct message * message = (struct message *)[data bytes];
message_t * message = (message_t *)[data bytes];
void (*method)(id, SEL, id) = (void (*)(id, SEL, id))[message->target methodForSelector: message->sel];
method( message->target, message->sel, message->u.object);
......@@ -263,6 +274,17 @@ static void * EventDispatcherMainLoop(void * user_data)
[data release];
}
- (void)callDelegateOfObject:(id) aTarget withDelegateMethod:(SEL)aSelector withNotificationName: (NSString *)aNotificationName
{
// [[NSNotificationCenter defaultCenter] postNotification: [NSNotification notificationWithName:aNotificationName object:aTarget]];
if (![aTarget delegate] || ![[aTarget delegate] respondsToSelector:aSelector])
return;
void (*method)(id, SEL, id) = (void (*)(id, SEL, id))[[aTarget delegate] methodForSelector: aSelector];
method( [aTarget delegate], aSelector, [NSNotification notificationWithName:aNotificationName object:aTarget]);
}
- (NSMutableArray *)messageQueue
{
return messageQueue;
......@@ -277,15 +299,4 @@ static void * EventDispatcherMainLoop(void * user_data)
{
return &queueLock;
}
- (void)callDelegateOfObject:(id) aTarget withDelegateMethod:(SEL)aSelector withNotificationName: (NSString *)aNotificationName
{
// [[NSNotificationCenter defaultCenter] postNotification: [NSNotification notificationWithName:aNotificationName object:aTarget]];
if (![aTarget delegate] || ![[aTarget delegate] respondsToSelector: aSelector])
return;
void (*method)(id, SEL, id) = (void (*)(id, SEL, id))[[aTarget delegate] methodForSelector: aSelector];
method( [aTarget delegate], aSelector, [NSNotification notificationWithName:aNotificationName object:aTarget]);
}
@end
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