Reputation: 1
is the MyThreadSafeMutableDictionary thread safe?
actually, i get some NSDictionary crash issues,
i just call [MyThreadSafeMutableDictionary objectForkey:@"key"]
and [MyThreadSafeMutableDictionary removeAllObjects] in different thread.
the call stack like:
EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x000a00130008000c
0
libobjc.A.dylib objc_msgSend + 8
1
CoreFoundation -[__NSDictionaryM objectForKey:] + 168
2
VSTThreadSafeMutableDictionary.m - line 154 __47-[VSTThreadSafeMutableDictionary objectForKey:]_block_invoke + 154
3
libdispatch.dylib _dispatch_client_callout + 20
4
libdispatch.dylib _dispatch_sync_invoke_and_complete + 56
5
MyThreadSafeMutableDictionary.m
MyThreadSafeMutableDictionary.m
line 153 -[VSTThreadSafeMutableDictionary objectForKey:] + 153**
**the MyThreadSafeMutableDictionary.h source code as follows:**
#import "MyThreadSafeMutableDictionary.h"
@interface MyThreadSafeMutableDictionary ()
@property (nonatomic, strong) NSMutableDictionary *mutableDictionary;
@end
@implementation MyThreadSafeMutableDictionary
+ (NSString *)queueName {
CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
NSString *uuid = (NSString *)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, uuidRef));
CFRelease(uuidRef);
NSString *queueName = [NSString stringWithFormat:@"com.my.thread.safe.Dictionary.%@", uuid];
return queueName;
}
+ (instancetype)dictionary {
MyThreadSafeMutableDictionary *mutableDictionary = [MyThreadSafeMutableDictionary new];
return mutableDictionary;
}
+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
MyThreadSafeMutableDictionary *mutableDictionary = [[MyThreadSafeMutableDictionary alloc] initWithCapacity:numItems];
return mutableDictionary;
}
+ (instancetype)dictionaryWithDictionary:(NSDictionary *)dict {
MyThreadSafeMutableDictionary *mutableDictionary = [self dictionary];
[mutableDictionary addEntriesFromDictionary:dict];
return mutableDictionary;
}
- (instancetype)init {
return [self initWithCapacity:0];
}
- (instancetype)initWithDictionary:(NSDictionary *)otherDictionary {
if (self = [self initWithCapacity:0]) {
[self addEntriesFromDictionary:otherDictionary];
}
return self;
}
- (instancetype)initWithCapacity:(NSUInteger)numItems {
if (self = [super init]) {
if (numItems == 0) {
_mutableDictionary = [NSMutableDictionary new];
} else {
_mutableDictionary = [NSMutableDictionary dictionaryWithCapacity:numItems];
}
_syncQueue = dispatch_queue_create([MyThreadSafeMutableDictionary.queueName UTF8String], DISPATCH_QUEUE_CONCURRENT);
}
return self;
}
- (void)removeObjectForKey:(id)aKey {
dispatch_barrier_async(self.syncQueue, ^{
[self.mutableDictionary removeObjectForKey:aKey];
});
}
- (void)setObject:(id)anObject forKey:(id<NSCopying>)aKey {
dispatch_barrier_async(self.syncQueue, ^{
[self.mutableDictionary setObject:anObject forKey:aKey];
});
}
- (void)setValue:(id)value forKey:(NSString *)key {
dispatch_barrier_async(self.syncQueue, ^{
[self.mutableDictionary setValue:value forKey:key];
});
}
- (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary {
dispatch_barrier_async(self.syncQueue, ^{
[self.mutableDictionary addEntriesFromDictionary:otherDictionary];
});
}
- (void)removeAllObjects {
dispatch_barrier_async(self.syncQueue, ^{
[self.mutableDictionary removeAllObjects];
});
}
- (void)removeObjectsForKeys:(NSArray *)keyArray {
dispatch_barrier_async(self.syncQueue, ^{
[self.mutableDictionary removeObjectsForKeys:keyArray];
});
}
- (NSArray *)keysSortedByValueUsingComparator:(NSComparator NS_NOESCAPE)cmptr {
__block NSArray *keysSortedArray = nil;
dispatch_sync(self.syncQueue, ^{
keysSortedArray = [self.mutableDictionary keysSortedByValueUsingComparator:cmptr];
});
return keysSortedArray;
}
- (NSArray *)keysSortedByValueWithOptions:(NSSortOptions)opts usingComparator:(NSComparator NS_NOESCAPE)cmptr {
__block NSArray *keysSortedArray = nil;
dispatch_sync(self.syncQueue, ^{
keysSortedArray = [self.mutableDictionary keysSortedByValueWithOptions:opts usingComparator:cmptr];
});
return keysSortedArray;
}
- (NSArray *)allKeys {
__block NSArray *allKeys = nil;
dispatch_sync(self.syncQueue, ^{
allKeys = [self.mutableDictionary allKeys];
});
return allKeys;
}
- (NSArray *)allValues {
__block NSArray *allValues = nil;
dispatch_sync(self.syncQueue, ^{
allValues = [self.mutableDictionary allValues];
});
return allValues;
}
- (NSDictionary *)copy {
__block NSDictionary *copyDictionary = nil;
dispatch_sync(self.syncQueue, ^{
copyDictionary = [self.mutableDictionary copy];
});
return copyDictionary;
}
- (NSMutableDictionary *)mutableCopy {
__block NSMutableDictionary *mutableCopyDictionary = nil;
dispatch_sync(self.syncQueue, ^{
mutableCopyDictionary = [self.mutableDictionary mutableCopy];
});
return mutableCopyDictionary;
}
- (id)objectForKey:(id)aKey {
__block id valueObject = nil;
dispatch_sync(self.syncQueue, ^{
valueObject = [self.mutableDictionary objectForKey:aKey];
});
return valueObject;
}
- (id)valueForKey:(NSString *)key {
__block id valueObject = nil;
dispatch_sync(self.syncQueue, ^{
valueObject = [self.mutableDictionary valueForKey:key];
});
return valueObject;
}
- (NSUInteger)count {
__block NSUInteger dictionaryCount = 0;
dispatch_sync(self.syncQueue, ^{
dictionaryCount = self.mutableDictionary.count;
});
return dictionaryCount;
}
@end
Upvotes: 0
Views: 22