12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
+
-
+
-
+
|
* LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
* file.
*/
#include "config.h"
#import "OFNotificationCenter.h"
#import "OFArray.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_THREADS
# import "OFMutex.h"
#endif
#import "OFSet.h"
#import "OFString.h"
@interface OFDefaultNotificationCenter: OFNotificationCenter
@end
@interface OFNotificationRegistration: OFObject
@interface OFNotificationHandler: OFObject
{
@public
id _observer;
SEL _selector;
unsigned long _selectorHash;
id _object;
}
- (instancetype)initWithObserver: (id)observer
selector: (SEL)selector
object: (id)object;
@end
static OFNotificationCenter *defaultCenter;
@implementation OFNotificationRegistration
@implementation OFNotificationHandler
- (instancetype)initWithObserver: (id)observer
selector: (SEL)selector
object: (id)object
{
self = [super init];
@try {
|
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
-
+
-
+
-
+
-
+
-
-
+
|
{
[_observer release];
[_object release];
[super dealloc];
}
- (bool)isEqual: (OFNotificationRegistration *)registration
- (bool)isEqual: (OFNotificationHandler *)handler
{
if (![registration isKindOfClass: [OFNotificationRegistration class]])
if (![handler isKindOfClass: [OFNotificationHandler class]])
return false;
if (![registration->_observer isEqual: _observer])
if (![handler->_observer isEqual: _observer])
return false;
if (!sel_isEqual(registration->_selector, _selector))
if (!sel_isEqual(handler->_selector, _selector))
return false;
if (registration->_object != _object &&
![registration->_object isEqual: _object])
if (handler->_object != _object && ![handler->_object isEqual: _object])
return false;
return true;
}
- (unsigned long)hash
{
|
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
|
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
|
-
-
+
+
-
+
-
-
-
+
-
-
+
+
+
+
+
-
-
+
+
-
-
+
-
-
+
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
|
- (void)addObserver: (id)observer
selector: (SEL)selector
name: (OFNotificationName)name
object: (id)object
{
void *pool = objc_autoreleasePoolPush();
OFNotificationRegistration *registration =
[[[OFNotificationRegistration alloc]
OFNotificationHandler *handler = [[[OFNotificationHandler alloc]
initWithObserver: observer
selector: selector
object: object] autorelease];
#ifdef OF_HAVE_THREADS
[_mutex lock];
@try {
#endif
OFMutableSet *notificationsForName =
[_notifications objectForKey: name];
if (notificationsForName == nil) {
notificationsForName = [OFMutableSet set];
[_notifications setObject: notificationsForName
forKey: name];
}
[notificationsForName addObject: registration];
[notificationsForName addObject: handler];
#endif
#ifdef OF_HAVE_THREADS
} @finally {
[_mutex unlock];
}
#endif
objc_autoreleasePoolPop(pool);
}
- (void)removeObserver: (id)observer
selector: (SEL)selector
name: (OFNotificationName)name
object: (id)object
{
void *pool = objc_autoreleasePoolPush();
OFNotificationRegistration *registration =
[[[OFNotificationRegistration alloc]
OFNotificationHandler *handler = [[[OFNotificationHandler alloc]
initWithObserver: observer
selector: selector
object: object] autorelease];
#ifdef OF_HAVE_THREADS
[_mutex lock];
@try {
[[_notifications objectForKey: name]
removeObject: registration];
#endif
[[_notifications objectForKey: name] removeObject: handler];
#ifdef OF_HAVE_THREADS
} @finally {
[_mutex unlock];
}
#endif
objc_autoreleasePoolPop(pool);
}
- (void)postNotification: (OFNotification *)notification
{
void *pool = objc_autoreleasePoolPush();
OFMutableArray *matchedHandlers = [OFMutableArray array];
#ifdef OF_HAVE_THREADS
[_mutex lock];
@try {
#endif
for (OFNotificationRegistration *registration in
[_notifications objectForKey: notification.name]) {
for (OFNotificationHandler *handler in
[_notifications objectForKey: notification.name])
void (*callback)(id, SEL, OFNotification *);
if (handler->_object == nil ||
if (registration->_object != nil &&
registration->_object != notification.object)
handler->_object == notification.object)
continue;
[matchedHandlers addObject: handler];
callback = (void (*)(id, SEL, OFNotification *))
[registration->_observer methodForSelector:
registration->_selector];
callback(registration->_observer,
registration->_selector, notification);
}
#endif
#ifdef OF_HAVE_THREADS
} @finally {
[_mutex unlock];
}
#endif
for (OFNotificationHandler *handler in matchedHandlers) {
void (*callback)(id, SEL, OFNotification *) =
(void (*)(id, SEL, OFNotification *))
[handler->_observer methodForSelector: handler->_selector];
callback(handler->_observer, handler->_selector, notification);
}
objc_autoreleasePoolPop(pool);
}
@end
@implementation OFDefaultNotificationCenter
- (instancetype)autorelease
{
return self;
|