/
YYThreadSafeArray.m
420 lines (319 loc) · 12.9 KB
/
YYThreadSafeArray.m
1
2
3
4
5
6
7
8
9
10
11
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
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
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
//
// YYThreadSafeArray.m
// YYKit <https://github.com/ibireme/YYKit>
//
// Created by ibireme on 14/10/21.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import "YYThreadSafeArray.h"
#import "NSArray+YYAdd.h"
#define INIT(...) self = super.init; \
if (!self) return nil; \
__VA_ARGS__; \
if (!_arr) return nil; \
_lock = dispatch_semaphore_create(1); \
return self;
#define LOCK(...) dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER); \
__VA_ARGS__; \
dispatch_semaphore_signal(_lock);
@implementation YYThreadSafeArray {
NSMutableArray *_arr; //Subclass a class cluster...
dispatch_semaphore_t _lock;
}
#pragma mark - init
- (instancetype)init {
INIT(_arr = [[NSMutableArray alloc] init]);
}
- (instancetype)initWithCapacity:(NSUInteger)numItems {
INIT(_arr = [[NSMutableArray alloc] initWithCapacity:numItems]);
}
- (instancetype)initWithArray:(NSArray *)array {
INIT(_arr = [[NSMutableArray alloc] initWithArray:array]);
}
- (instancetype)initWithObjects:(const id[])objects count:(NSUInteger)cnt {
INIT(_arr = [[NSMutableArray alloc] initWithObjects:objects count:cnt]);
}
- (instancetype)initWithContentsOfFile:(NSString *)path {
INIT(_arr = [[NSMutableArray alloc] initWithContentsOfFile:path]);
}
- (instancetype)initWithContentsOfURL:(NSURL *)url {
INIT(_arr = [[NSMutableArray alloc] initWithContentsOfURL:url]);
}
#pragma mark - method
- (NSUInteger)count {
LOCK(NSUInteger count = _arr.count); return count;
}
- (id)objectAtIndex:(NSUInteger)index {
LOCK(id obj = [_arr objectAtIndex:index]); return obj;
}
- (NSArray *)arrayByAddingObject:(id)anObject {
LOCK(NSArray * arr = [_arr arrayByAddingObject:anObject]); return arr;
}
- (NSArray *)arrayByAddingObjectsFromArray:(NSArray *)otherArray {
LOCK(NSArray * arr = [_arr arrayByAddingObjectsFromArray:otherArray]); return arr;
}
- (NSString *)componentsJoinedByString:(NSString *)separator {
LOCK(NSString * str = [_arr componentsJoinedByString:separator]); return str;
}
- (BOOL)containsObject:(id)anObject {
LOCK(BOOL c = [_arr containsObject:anObject]); return c;
}
- (NSString *)description {
LOCK(NSString * d = _arr.description); return d;
}
- (NSString *)descriptionWithLocale:(id)locale {
LOCK(NSString * d = [_arr descriptionWithLocale:locale]); return d;
}
- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level {
LOCK(NSString * d = [_arr descriptionWithLocale:locale indent:level]); return d;
}
- (id)firstObjectCommonWithArray:(NSArray *)otherArray {
LOCK(id o = [_arr firstObjectCommonWithArray:otherArray]); return o;
}
- (void)getObjects:(id __unsafe_unretained[])objects range:(NSRange)range {
LOCK([_arr getObjects:objects range:range]);
}
- (NSUInteger)indexOfObject:(id)anObject {
LOCK(NSUInteger i = [_arr indexOfObject:anObject]); return i;
}
- (NSUInteger)indexOfObject:(id)anObject inRange:(NSRange)range {
LOCK(NSUInteger i = [_arr indexOfObject:anObject inRange:range]); return i;
}
- (NSUInteger)indexOfObjectIdenticalTo:(id)anObject {
LOCK(NSUInteger i = [_arr indexOfObjectIdenticalTo:anObject]); return i;
}
- (NSUInteger)indexOfObjectIdenticalTo:(id)anObject inRange:(NSRange)range {
LOCK(NSUInteger i = [_arr indexOfObjectIdenticalTo:anObject inRange:range]); return i;
}
- (id)firstObject {
LOCK(id o = _arr.firstObject); return o;
}
- (id)lastObject {
LOCK(id o = _arr.lastObject); return o;
}
- (NSEnumerator *)objectEnumerator {
LOCK(NSEnumerator * e = [_arr objectEnumerator]); return e;
}
- (NSEnumerator *)reverseObjectEnumerator {
LOCK(NSEnumerator * e = [_arr reverseObjectEnumerator]); return e;
}
- (NSData *)sortedArrayHint {
LOCK(NSData * d = [_arr sortedArrayHint]); return d;
}
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context {
LOCK(NSArray * arr = [_arr sortedArrayUsingFunction:comparator context:context]) return arr;
}
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context hint:(NSData *)hint {
LOCK(NSArray * arr = [_arr sortedArrayUsingFunction:comparator context:context hint:hint]); return arr;
}
- (NSArray *)sortedArrayUsingSelector:(SEL)comparator {
LOCK(NSArray * arr = [_arr sortedArrayUsingSelector:comparator]); return arr;
}
- (NSArray *)subarrayWithRange:(NSRange)range {
LOCK(NSArray * arr = [_arr subarrayWithRange:range]) return arr;
}
- (void)makeObjectsPerformSelector:(SEL)aSelector {
LOCK([_arr makeObjectsPerformSelector:aSelector]);
}
- (void)makeObjectsPerformSelector:(SEL)aSelector withObject:(id)argument {
LOCK([_arr makeObjectsPerformSelector:aSelector withObject:argument]);
}
- (NSArray *)objectsAtIndexes:(NSIndexSet *)indexes {
LOCK(NSArray * arr = [_arr objectsAtIndexes:indexes]); return arr;
}
- (id)objectAtIndexedSubscript:(NSUInteger)idx {
LOCK(id o = [_arr objectAtIndexedSubscript:idx]); return o;
}
- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block {
LOCK([_arr enumerateObjectsUsingBlock:block]);
}
- (void)enumerateObjectsWithOptions:(NSEnumerationOptions)opts usingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block {
LOCK([_arr enumerateObjectsWithOptions:opts usingBlock:block]);
}
- (void)enumerateObjectsAtIndexes:(NSIndexSet *)s options:(NSEnumerationOptions)opts usingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block {
LOCK([_arr enumerateObjectsAtIndexes:s options:opts usingBlock:block]);
}
- (NSUInteger)indexOfObjectPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate {
LOCK(NSUInteger i = [_arr indexOfObjectPassingTest:predicate]); return i;
}
- (NSUInteger)indexOfObjectWithOptions:(NSEnumerationOptions)opts passingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate {
LOCK(NSUInteger i = [_arr indexOfObjectWithOptions:opts passingTest:predicate]); return i;
}
- (NSUInteger)indexOfObjectAtIndexes:(NSIndexSet *)s options:(NSEnumerationOptions)opts passingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate {
LOCK(NSUInteger i = [_arr indexOfObjectAtIndexes:s options:opts passingTest:predicate]); return i;
}
- (NSIndexSet *)indexesOfObjectsPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate {
LOCK(NSIndexSet * i = [_arr indexesOfObjectsPassingTest:predicate]); return i;
}
- (NSIndexSet *)indexesOfObjectsWithOptions:(NSEnumerationOptions)opts passingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate {
LOCK(NSIndexSet * i = [_arr indexesOfObjectsWithOptions:opts passingTest:predicate]); return i;
}
- (NSIndexSet *)indexesOfObjectsAtIndexes:(NSIndexSet *)s options:(NSEnumerationOptions)opts passingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate {
LOCK(NSIndexSet * i = [_arr indexesOfObjectsAtIndexes:s options:opts passingTest:predicate]); return i;
}
- (NSArray *)sortedArrayUsingComparator:(NSComparator)cmptr {
LOCK(NSArray * a = [_arr sortedArrayUsingComparator:cmptr]); return a;
}
- (NSArray *)sortedArrayWithOptions:(NSSortOptions)opts usingComparator:(NSComparator)cmptr {
LOCK(NSArray * a = [_arr sortedArrayWithOptions:opts usingComparator:cmptr]); return a;
}
- (NSUInteger)indexOfObject:(id)obj inSortedRange:(NSRange)r options:(NSBinarySearchingOptions)opts usingComparator:(NSComparator)cmp {
LOCK(NSUInteger i = [_arr indexOfObject:obj inSortedRange:r options:opts usingComparator:cmp]); return i;
}
#pragma mark - mutable
- (void)addObject:(id)anObject {
LOCK([_arr addObject:anObject]);
}
- (void)insertObject:(id)anObject atIndex:(NSUInteger)index {
LOCK([_arr insertObject:anObject atIndex:index]);
}
- (void)removeLastObject {
LOCK([_arr removeLastObject]);
}
- (void)removeObjectAtIndex:(NSUInteger)index {
LOCK([_arr removeObjectAtIndex:index]);
}
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject {
LOCK([_arr replaceObjectAtIndex:index withObject:anObject]);
}
- (void)addObjectsFromArray:(NSArray *)otherArray {
LOCK([_arr addObjectsFromArray:otherArray]);
}
- (void)exchangeObjectAtIndex:(NSUInteger)idx1 withObjectAtIndex:(NSUInteger)idx2 {
LOCK([_arr exchangeObjectAtIndex:idx1 withObjectAtIndex:idx2]);
}
- (void)removeAllObjects {
LOCK([_arr removeAllObjects]);
}
- (void)removeObject:(id)anObject inRange:(NSRange)range {
LOCK([_arr removeObject:anObject inRange:range]);
}
- (void)removeObject:(id)anObject {
LOCK([_arr removeObject:anObject]);
}
- (void)removeObjectIdenticalTo:(id)anObject inRange:(NSRange)range {
LOCK([_arr removeObjectIdenticalTo:anObject inRange:range]);
}
- (void)removeObjectIdenticalTo:(id)anObject {
LOCK([_arr removeObjectIdenticalTo:anObject]);
}
- (void)removeObjectsInArray:(NSArray *)otherArray {
LOCK([_arr removeObjectsInArray:otherArray]);
}
- (void)removeObjectsInRange:(NSRange)range {
LOCK([_arr removeObjectsInRange:range]);
}
- (void)replaceObjectsInRange:(NSRange)range withObjectsFromArray:(NSArray *)otherArray range:(NSRange)otherRange {
LOCK([_arr replaceObjectsInRange:range withObjectsFromArray:otherArray range:otherRange]);
}
- (void)replaceObjectsInRange:(NSRange)range withObjectsFromArray:(NSArray *)otherArray {
LOCK([_arr replaceObjectsInRange:range withObjectsFromArray:otherArray]);
}
- (void)setArray:(NSArray *)otherArray {
LOCK([_arr setArray:otherArray]);
}
- (void)sortUsingFunction:(NSInteger (*)(id, id, void *))compare context:(void *)context {
LOCK([_arr sortUsingFunction:compare context:context]);
}
- (void)sortUsingSelector:(SEL)comparator {
LOCK([_arr sortUsingSelector:comparator]);
}
- (void)insertObjects:(NSArray *)objects atIndexes:(NSIndexSet *)indexes {
LOCK([_arr insertObjects:objects atIndexes:indexes]);
}
- (void)removeObjectsAtIndexes:(NSIndexSet *)indexes {
LOCK([_arr removeObjectsAtIndexes:indexes]);
}
- (void)replaceObjectsAtIndexes:(NSIndexSet *)indexes withObjects:(NSArray *)objects {
LOCK([_arr replaceObjectsAtIndexes:indexes withObjects:objects]);
}
- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx {
LOCK([_arr setObject:obj atIndexedSubscript:idx]);
}
- (void)sortUsingComparator:(NSComparator)cmptr {
LOCK([_arr sortUsingComparator:cmptr]);
}
- (void)sortWithOptions:(NSSortOptions)opts usingComparator:(NSComparator)cmptr {
LOCK([_arr sortWithOptions:opts usingComparator:cmptr]);
}
- (BOOL)isEqualToArray:(NSArray *)otherArray {
if (otherArray == self) return YES;
if ([otherArray isKindOfClass:YYThreadSafeArray.class]) {
YYThreadSafeArray *other = (id)otherArray;
BOOL isEqual;
dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER);
dispatch_semaphore_wait(other->_lock, DISPATCH_TIME_FOREVER);
isEqual = [_arr isEqualToArray:other->_arr];
dispatch_semaphore_signal(other->_lock);
dispatch_semaphore_signal(_lock);
return isEqual;
}
return NO;
}
#pragma mark - protocol
- (id)copyWithZone:(NSZone *)zone {
return [self mutableCopyWithZone:zone];
}
- (id)mutableCopyWithZone:(NSZone *)zone {
LOCK(id copiedDictionary = [[self.class allocWithZone:zone] initWithArray:_arr]);
return copiedDictionary;
}
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
objects:(id __unsafe_unretained[])stackbuf
count:(NSUInteger)len {
LOCK(NSUInteger count = [_arr countByEnumeratingWithState:state objects:stackbuf count:len]);
return count;
}
- (BOOL)isEqual:(id)object {
if (object == self) return YES;
if ([object isKindOfClass:YYThreadSafeArray.class]) {
YYThreadSafeArray *other = object;
BOOL isEqual;
dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER);
dispatch_semaphore_wait(other->_lock, DISPATCH_TIME_FOREVER);
isEqual = [_arr isEqual:other->_arr];
dispatch_semaphore_signal(other->_lock);
dispatch_semaphore_signal(_lock);
return isEqual;
}
return NO;
}
- (NSUInteger)hash {
LOCK(NSUInteger hash = [_arr hash]);
return hash;
}
#pragma mark - custom methods for NSArray(YYAdd)
- (id)randomObject {
LOCK(id o = [_arr randomObject]) return o;
}
- (id)objectOrNilAtIndex:(NSUInteger)index {
LOCK(id o = [_arr objectOrNilAtIndex:index]) return o;
}
- (void)removeFirstObject {
LOCK([_arr removeFirstObject]);
}
- (id)popFirstObject {
LOCK(id o = [_arr popFirstObject]) return o;
}
- (id)popLastObject {
LOCK(id o = [_arr popLastObject]) return o;
}
- (void)appendObjects:(NSArray *)objects {
LOCK([_arr appendObjects:objects]);
}
- (void)prependObjects:(NSArray *)objects {
LOCK([_arr prependObjects:objects]);
}
- (void)insertObjects:(NSArray *)objects atIndex:(NSUInteger)index {
LOCK([_arr insertObjects:objects atIndex:index]);
}
- (void)reverse {
LOCK([_arr reverse]);
}
- (void)shuffle {
LOCK([_arr shuffle]);
}
@end