Created
January 19, 2018 06:20
-
-
Save nhatlee/bc7035dd87b7b1293aacf15861e1e05d to your computer and use it in GitHub Desktop.
Thread safe for NSMutableArray
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// PMThreadSafeMutableArray.m | |
// | |
// Created by nhatlee on 1/19/18. | |
// Copyright © 2018 nhatlee. All rights reserved. | |
// | |
#import "PMThreadSafeMutableArray.h" | |
#import <libkern/OSAtomic.h> | |
#define LOCKED(...) OSSpinLockLock(&_lock);\ | |
__VA_ARGS__;\ | |
OSSpinLockUnlock(&_lock); | |
@implementation PMThreadSafeMutableArray { | |
OSSpinLock _lock; | |
NSMutableArray *_array; | |
} | |
#pragma mark - NSObject | |
- (id)init { | |
return [self initWithCapacity:0]; | |
} | |
-(id)initWithArray:(NSArray *)array { | |
if(self = [self initWithCapacity:array.count]) { | |
[array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { | |
_array[idx] = obj; | |
}]; | |
} | |
return self; | |
} | |
-(id)initWithCapacity:(NSUInteger)numItems { | |
if(self = [super init]) { | |
_array = [[NSMutableArray alloc] initWithCapacity:numItems]; | |
_lock = OS_SPINLOCK_INIT; | |
} | |
return self; | |
} | |
#pragma mark - NSMutableArray | |
-(void)addObject:(id)anObject { | |
LOCKED([_array addObject: anObject]); | |
} | |
-(void)addObjectsFromArray:(NSArray *)otherArray { | |
LOCKED([_array addObjectsFromArray:otherArray]); | |
} | |
-(void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject { | |
LOCKED([_array replaceObjectAtIndex:index withObject:anObject]); | |
} | |
-(void)replaceObjectsAtIndexes:(NSIndexSet *)indexes withObjects:(NSArray *)objects { | |
LOCKED([_array replaceObjectsAtIndexes:indexes withObjects:objects]); | |
} | |
-(void)removeObject:(id)anObject { | |
LOCKED([_array removeObject:anObject]); | |
} | |
-(void)removeAllObjects { | |
LOCKED([_array removeAllObjects]); | |
} | |
-(NSUInteger)count { | |
LOCKED(NSUInteger count = _array.count); | |
return count; | |
} | |
-(id)objectAtIndex:(NSUInteger)index { | |
LOCKED(id obj = _array[index]); | |
return obj; | |
} | |
-(NSUInteger)indexOfObject:(id)anObject { | |
LOCKED(NSUInteger idx = [_array indexOfObject:anObject]); | |
return idx; | |
} | |
-(id)copyWithZone:(NSZone *)zone { | |
return [self mutableCopyWithZone:zone]; | |
} | |
-(id)mutableCopyWithZone:(NSZone *)zone { | |
LOCKED(id copiedArray = [[self.class allocWithZone:zone] initWithArray:_array]); | |
return copiedArray; | |
} | |
-(NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id _Nullable __unsafe_unretained [])buffer count:(NSUInteger)len { | |
LOCKED(NSUInteger count = [[_array copy] countByEnumeratingWithState:state objects:buffer count:len]); | |
return count; | |
} | |
-(void)performLockWithArray:(void (^)(NSArray *anArray))block { | |
if(block) LOCKED(block(_array)); | |
} | |
-(BOOL)isEqual:(id)object { | |
if (object == self) return YES; | |
if([object isKindOfClass:[PMThreadSafeMutableArray class]]) { | |
PMThreadSafeMutableArray *other = object; | |
__block BOOL isEqual = NO; | |
[other performLockWithArray:^(NSArray *anArray) { | |
[self performLockWithArray:^(NSArray *otherArray) { | |
isEqual = [anArray isEqual:otherArray]; | |
}]; | |
}]; | |
return isEqual; | |
} | |
return NO; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment