ObjFW  Diff

Differences From Artifact [c832dbfaa5]:

To Artifact [7d4ea0e843]:


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;