00001
00002
00003
00004
00005
00006
00007
00008
00009 #import "LLNotificationCenter.h"
00010
00011
00012 @implementation LLNotificationCenter
00013
00014 LLNotificationCenter *defaultCenter;
00015 NSLock *synchronizeAccess;
00016 NSMutableDictionary *senders;
00017 LLDOReceiver *receiver;
00018 NSString *mainThreadID;
00019 bool sendEvents = YES;
00020
00021 - (id) init {
00022 self = [super init];
00023 if (self != nil) {
00024 listeners = [[NSMutableDictionary alloc] init];
00025 useLocks = NO;
00026 synchronizeAccess = [[NSLock alloc] init];
00027 timeOut = 2;
00028
00029
00030 receiver = [[LLDOReceiver alloc] init];
00031
00032 [receiver setTarget:self withSelector:@selector(remotelyPostedEvent:)];
00033
00034 senders = [[NSMutableDictionary alloc] init];
00035
00036 mainThreadID = [NSString stringWithFormat:@"%d", [NSThread currentThread]];
00037 [mainThreadID retain];
00038 }
00039 return self;
00040 }
00041
00042 + (LLNotificationCenter*) defaultCenter {
00043 if (defaultCenter == nil) {
00044 defaultCenter = [[LLNotificationCenter alloc] init];
00045 }
00046 return defaultCenter;
00047 }
00048
00049 - (void)addObserver:(id)notificationObserver
00050 selector:(SEL)notificationSelector
00051 name:(NSString *)notificationName {
00052
00053 [self addObserver:notificationObserver
00054 selector:notificationSelector
00055 name:notificationName
00056 object:nil
00057 useLocks:NO
00058 useMainRunLoop:NO];
00059 }
00060
00061 - (void)addObserver:(id)notificationObserver
00062 selector:(SEL)notificationSelector
00063 name:(NSString *)notificationName
00064 object:(NSString *)notificationSender {
00065
00066 [self addObserver:notificationObserver
00067 selector:notificationSelector
00068 name:notificationName
00069 object:notificationSender
00070 useLocks:NO
00071 useMainRunLoop:NO];
00072 }
00073
00074 - (void)addObserver:(id)notificationObserver
00075 selector:(SEL)notificationSelector
00076 name:(NSString *)notificationName
00077 object:(NSString *)notificationSender
00078 useLocks:(bool)protect {
00079 [self addObserver:notificationObserver
00080 selector:notificationSelector
00081 name:notificationName
00082 object:notificationSender
00083 useLocks:protect
00084 useMainRunLoop:NO];
00085 }
00086
00087 - (void)addObserver:(id)notificationObserver
00088 selector:(SEL)notificationSelector
00089 name:(NSString *)notificationName
00090 object:(NSString *)notificationSender
00091 useLocks:(bool)protect
00092 useMainRunLoop:(bool)useMainLoop {
00093
00094 if (notificationObserver == nil) {
00095 NSLog(@"LLNotificationCenter.addObserver notificationObserver cannot be nil");
00096 return;
00097 }
00098 if (notificationSelector == nil) {
00099 NSLog(@"LLNotificationCenter.addObserver notificationSelector cannot be nil");
00100 return;
00101 }
00102
00103 if (useMainLoop) {
00104 protect = NO;
00105 }
00106
00107
00108 LLNotificationCenterEntry *newListener = [[LLNotificationCenterEntry alloc] initWithNotificationName:notificationName
00109 source:notificationSender
00110 target:notificationObserver
00111 selector:notificationSelector
00112 useLocks:protect
00113 useMainLoop:useMainLoop];
00114
00115
00116 NSMutableArray *listenersForThisKey = [listeners valueForKey:notificationName];
00117 if (listenersForThisKey == nil) {
00118
00119 listenersForThisKey = [[NSMutableArray alloc] init];
00120 [listeners setValue: listenersForThisKey forKey:notificationName];
00121 }
00122
00123
00124 [listenersForThisKey addObject:newListener];
00125
00126 return;
00127 }
00128
00129 - (void) remotelyPostedEvent:(LLNotificationCenterEntry *)listener {
00130
00131
00132
00133
00134 id target = [listener target];
00135 SEL selector = [listener selector];
00136 id userInfo = [listener userData];
00137
00138
00139 [target performSelector:selector withObject:userInfo];
00140 }
00141
00142 - (LLDOSender *) getSenderForMyThread {
00143
00144 NSString *threadID = [NSString stringWithFormat:@"%d", [NSThread currentThread]];
00145
00146
00147 if ([threadID isEqualToString: mainThreadID]) {
00148 return nil;
00149 }
00150
00151 LLDOSender *sender = [senders objectForKey:threadID];
00152 if (sender == nil) {
00153
00154 NSLog(@"LLNotificationCenter.getSenderForMyThread creating sender for thread %d", threadID);
00155 sender = [[LLDOSender alloc] init];
00156 [senders setObject:sender forKey:threadID];
00157 }
00158 return sender;
00159 }
00160
00161 - (void) setEnable:(bool)enable {
00162 sendEvents = enable;
00163 }
00164
00165 - (void) postNotificationName:(NSString *)name object:(id) sender userInfo:(id)userInfo {
00166
00167 if (!sendEvents) {
00168 return;
00169 }
00170
00171
00172
00173
00174 bool hasObserver = NO;
00175
00176 if (name == nil) {
00177 NSLog(@"LLNotificationCenter.postNotification nil strings are no longer accepted");
00178 return;
00179 }
00180
00181 NSMutableArray *listenersForThisKey = [listeners valueForKey:name];
00182
00183
00184 for (int i = 0; i < [listenersForThisKey count]; i++) {
00185 LLNotificationCenterEntry *listener = [listenersForThisKey objectAtIndex:i];
00186
00187
00188 if (([listener source] == sender) || ([listener source] == nil)) {
00189 hasObserver = YES;
00190 id target = [listener target];
00191 SEL selector = [listener selector];
00192
00193 if (useLocks || [listener useLocks]) {
00194
00195 if ([synchronizeAccess lockBeforeDate:[NSDate dateWithTimeIntervalSinceNow:timeOut]]) {
00196
00197 [target performSelector:selector withObject:userInfo];
00198 [synchronizeAccess unlock];
00199 } else {
00200 NSLog(@"LLNotificationCenter.postNotificationName waited %d seconds for lock, discarding event");
00201 return;
00202 }
00203 } else {
00204 if ([listener useMainLoop]) {
00205
00206
00207
00208
00209 [listener setUserData:userInfo];
00210
00211 LLDOSender *sender = [self getSenderForMyThread];
00212
00213 if (sender != nil) {
00214 [sender invokeRemoteObjectWithUserData:listener];
00215 } else {
00216 [target performSelector:selector withObject:userInfo];
00217 }
00218
00219 } else {
00220 [target performSelector:selector withObject:userInfo];
00221 }
00222 }
00223 }
00224 }
00225 if (!hasObserver) {
00226 NSLog(@"LLNotificationCenter.postNotificationName WARNING notification %@ has no observer", name);
00227 }
00228 }
00229
00230 - (void)removeObserver:(id)notificationObserver
00231 name:(NSString *)notificationName {
00232 NSLog(@"LLNotificationCenter.removeObserver %@", notificationObserver);
00233
00234 int removed = 0;
00235
00236
00237
00238 unsigned int i, count = [[listeners allKeys] count];
00239 for (i = 0; i < count; i++) {
00240
00241
00242 NSMutableArray *toBeRemovedListners = [[NSMutableArray alloc] init];
00243
00244 NSString *key = [[listeners allKeys] objectAtIndex:i];
00245 NSMutableArray *listenersForThisKey = [listeners objectForKey:key];
00246
00247
00248 for (int i = 0; i < [listenersForThisKey count]; i++) {
00249 LLNotificationCenterEntry *listener = [listenersForThisKey objectAtIndex:i];
00250
00251 if ([listener target] == notificationObserver) {
00252
00253 if ([[listener name] isEqualToString:notificationName] ||
00254 (notificationName == nil)) {
00255
00256 [toBeRemovedListners addObject:listener];
00257 }
00258 }
00259 }
00260
00261
00262 [listenersForThisKey removeObjectsInArray:toBeRemovedListners];
00263 removed += [toBeRemovedListners count];
00264 [toBeRemovedListners release];
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 }
00275 NSLog(@"LLNotificationCenter.removeObserver removed %d occurences", removed);
00276 }
00277
00278 - (void) postNotificationName:(NSString *)name {
00279 [self postNotificationName:name object:self userInfo:nil];
00280 }
00281
00282 - (void) postNotificationName:(NSString *)name userInfo:(id)userInfo {
00283 [self postNotificationName:name object:self userInfo:userInfo];
00284 }
00285
00286 - (bool) useLocks {
00287 return useLocks;
00288 }
00289
00290 - (void) setUseLocks:(bool)protect {
00291 useLocks = protect;
00292 }
00293
00294 - (int) timeOut {
00295 return timeOut;
00296 }
00297
00298 - (void) setTimeOut:(int)interval {
00299 timeOut = interval;
00300 }
00301
00302 @end