Skip to content

Instantly share code, notes, and snippets.

@nhatlee
Created January 19, 2018 06:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nhatlee/bc7035dd87b7b1293aacf15861e1e05d to your computer and use it in GitHub Desktop.
Save nhatlee/bc7035dd87b7b1293aacf15861e1e05d to your computer and use it in GitHub Desktop.
Thread safe for NSMutableArray
//
// 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