]> git.saurik.com Git - apple/security.git/blob - keychain/ckks/CKKSListenerCollection.m
Security-59754.80.3.tar.gz
[apple/security.git] / keychain / ckks / CKKSListenerCollection.m
1
2 #if OCTAGON
3
4 #import "keychain/ckks/CKKSListenerCollection.h"
5 #import "keychain/ot/ObjCImprovements.h"
6
7 @interface CKKSListenerCollection ()
8 @property NSString* name;
9 @property NSMapTable<dispatch_queue_t, id>* listeners;
10 @end
11
12 @implementation CKKSListenerCollection
13
14 - (instancetype)initWithName:(NSString*)name
15 {
16 if((self = [super init])) {
17 _name = name;
18 // Backwards from how we'd like, but it's the best way to have weak pointers to ListenerTypes.
19 _listeners = [NSMapTable strongToWeakObjectsMapTable];
20 }
21 return self;
22 }
23
24 - (NSString*)description
25 {
26 @synchronized(self.listeners) {
27 return [NSString stringWithFormat:@"<CKKSListenerCollection(%@): %@>", self.name, [[self.listeners objectEnumerator] allObjects]];
28 }
29 }
30
31 - (void)registerListener:(id)listener
32 {
33 @synchronized(self.listeners) {
34 bool alreadyRegisteredListener = false;
35 NSEnumerator *enumerator = [self.listeners objectEnumerator];
36 id value;
37
38 while ((value = [enumerator nextObject])) {
39 // actually use pointer comparison
40 alreadyRegisteredListener |= (value == listener);
41 }
42
43 if(listener && !alreadyRegisteredListener) {
44 NSString* queueName = [NSString stringWithFormat: @"%@-%@", self.name, listener];
45
46 dispatch_queue_t objQueue = dispatch_queue_create([queueName UTF8String], DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL);
47 [self.listeners setObject: listener forKey: objQueue];
48 }
49 }
50 }
51
52 - (void)iterateListeners:(void (^)(id))block
53 {
54 @synchronized(self.listeners) {
55 NSEnumerator *enumerator = [self.listeners keyEnumerator];
56 dispatch_queue_t dq;
57
58 // Queue up the changes for each listener.
59 while ((dq = [enumerator nextObject])) {
60 id listener = [self.listeners objectForKey: dq];
61 WEAKIFY(listener);
62
63 if(listener) {
64 dispatch_async(dq, ^{
65 STRONGIFY(listener);
66 block(listener);
67 });
68 }
69 }
70 }
71 }
72
73 @end
74
75 #endif // OCTAGON