user29821503
user29821503

Reputation: 1

is the MyThreadSafeMutableDictionary thread safe。 if unsafe, what's the problem。

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

Answers (0)

Related Questions