Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save sunuslee/baea73bc3b846512d0b5 to your computer and use it in GitHub Desktop.

Select an option

Save sunuslee/baea73bc3b846512d0b5 to your computer and use it in GitHub Desktop.

Revisions

  1. @steipete steipete revised this gist Dec 6, 2013. 1 changed file with 80 additions and 16 deletions.
    96 changes: 80 additions & 16 deletions PSPDFThreadSafeMutableDictionary.m
    Original file line number Diff line number Diff line change
    @@ -29,12 +29,28 @@ @interface PSPDFThreadSafeMutableDictionary : NSMutableDictionary

    // ----------------------------------------------------------------

    //
    // PSPDFThreadSafeMutableDictionary.m
    // PSPDFKit
    //
    // Copyright (c) 2013 PSPDFKit GmbH. All rights reserved.
    //
    // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY AUSTRIAN COPYRIGHT LAW
    // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE PSPDFKIT LICENSE AGREEMENT.
    // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
    // This notice may not be removed from this file.
    //

    #import "PSPDFThreadSafeMutableDictionary.h"
    #import <libkern/OSAtomic.h>

    #define LOCKED(...) OSSpinLockLock(&_lock); \
    __VA_ARGS__; \
    OSSpinLockUnlock(&_lock);

    @implementation PSPDFThreadSafeMutableDictionary {
    OSSpinLock _lock;
    NSMutableDictionary *_dictionary; // Class Cluster
    NSMutableDictionary *_dictionary; // Class Cluster!
    }

    ///////////////////////////////////////////////////////////////////////////////////////////
    @@ -65,36 +81,84 @@ - (id)initWithCapacity:(NSUInteger)capacity {
    #pragma mark - NSMutableDictionary

    - (void)setObject:(id)anObject forKey:(id<NSCopying>)aKey {
    OSSpinLockLock(&_lock);
    _dictionary[aKey] = anObject;
    OSSpinLockUnlock(&_lock);
    LOCKED(_dictionary[aKey] = anObject)
    }

    - (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary {
    LOCKED([_dictionary addEntriesFromDictionary:otherDictionary]);
    }

    - (void)setDictionary:(NSDictionary *)otherDictionary {
    LOCKED([_dictionary setDictionary:otherDictionary]);
    }

    - (void)removeObjectForKey:(id)aKey {
    OSSpinLockLock(&_lock);
    [_dictionary removeObjectForKey:aKey];
    OSSpinLockUnlock(&_lock);
    LOCKED([_dictionary removeObjectForKey:aKey])
    }

    - (void)removeAllObjects {
    LOCKED([_dictionary removeAllObjects]);
    }

    - (NSUInteger)count {
    OSSpinLockLock(&_lock);
    NSUInteger count = _dictionary.count;
    OSSpinLockUnlock(&_lock);
    LOCKED(NSUInteger count = _dictionary.count)
    return count;
    }

    - (NSArray *)allKeys {
    LOCKED(NSArray *allKeys = _dictionary.allKeys)
    return allKeys;
    }

    - (NSArray *)allValues {
    LOCKED(NSArray *allValues = _dictionary.allValues)
    return allValues;
    }

    - (id)objectForKey:(id)aKey {
    OSSpinLockLock(&_lock);
    id obj = _dictionary[aKey];
    OSSpinLockUnlock(&_lock);
    LOCKED(id obj = _dictionary[aKey])
    return obj;
    }

    - (NSEnumerator *)keyEnumerator {
    OSSpinLockLock(&_lock);
    NSEnumerator *keyEnumerator = [_dictionary keyEnumerator];
    OSSpinLockUnlock(&_lock);
    LOCKED(NSEnumerator *keyEnumerator = [_dictionary keyEnumerator])
    return keyEnumerator;
    }

    - (id)copyWithZone:(NSZone *)zone {
    return [self mutableCopyWithZone:zone];
    }

    - (id)mutableCopyWithZone:(NSZone *)zone {
    LOCKED(id copiedDictionary = [[self.class allocWithZone:zone] initWithDictionary:_dictionary])
    return copiedDictionary;
    }

    - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
    objects:(id __unsafe_unretained [])stackbuf
    count:(NSUInteger)len {
    LOCKED(NSUInteger count = [[_dictionary copy] countByEnumeratingWithState:state objects:stackbuf count:len]);
    return count;
    }

    - (void)performLockedWithDictionary:(void (^)(NSDictionary *dictionary))block {
    if (block) LOCKED(block(_dictionary));
    }

    - (BOOL)isEqual:(id)object {
    if (object == self) return YES;

    if ([object isKindOfClass:PSPDFThreadSafeMutableDictionary.class]) {
    PSPDFThreadSafeMutableDictionary *other = object;
    __block BOOL isEqual = NO;
    [other performLockedWithDictionary:^(NSDictionary *dictionary) {
    [self performLockedWithDictionary:^(NSDictionary *otherDictionary) {
    isEqual = [dictionary isEqual:otherDictionary];
    }];
    }];
    return isEqual;
    }
    return NO;
    }

    @end
  2. @steipete steipete revised this gist Jul 4, 2013. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions PSPDFThreadSafeMutableDictionary.m
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    //
    // PSPDFThreadSafeMutableDictionary.m
    // PSPDFThreadSafeMutableDictionary.m
    //
    // Copyright (c) 2013 Peter Steinberger, PSPDFKit GmbH. All rights reserved.
    // Copyright (c) 2013 Peter Steinberger, PSPDFKit GmbH. All rights reserved.
    //
    // Permission is hereby granted, free of charge, to any person obtaining a copy
    // of this software and associated documentation files (the "Software"), to deal
  3. @steipete steipete created this gist Jul 4, 2013.
    100 changes: 100 additions & 0 deletions PSPDFThreadSafeMutableDictionary.m
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,100 @@
    //
    // PSPDFThreadSafeMutableDictionary.m
    //
    // Copyright (c) 2013 Peter Steinberger, PSPDFKit GmbH. All rights reserved.
    //
    // Permission is hereby granted, free of charge, to any person obtaining a copy
    // of this software and associated documentation files (the "Software"), to deal
    // in the Software without restriction, including without limitation the rights
    // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    // copies of the Software, and to permit persons to whom the Software is
    // furnished to do so, subject to the following conditions:
    //
    // The above copyright notice and this permission notice shall be included in
    // all copies or substantial portions of the Software.
    //
    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    // THE SOFTWARE.

    #import <Foundation/Foundation.h>

    // Dictionary-Subclasss whose primitive operations are thread safe.
    @interface PSPDFThreadSafeMutableDictionary : NSMutableDictionary
    @end

    // ----------------------------------------------------------------

    #import "PSPDFThreadSafeMutableDictionary.h"
    #import <libkern/OSAtomic.h>

    @implementation PSPDFThreadSafeMutableDictionary {
    OSSpinLock _lock;
    NSMutableDictionary *_dictionary; // Class Cluster
    }

    ///////////////////////////////////////////////////////////////////////////////////////////
    #pragma mark - NSObject

    - (id)init {
    return [self initWithCapacity:0];
    }

    - (id)initWithObjects:(NSArray *)objects forKeys:(NSArray *)keys {
    if ((self = [self initWithCapacity:objects.count])) {
    [objects enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    _dictionary[keys[idx]] = obj;
    }];
    }
    return self;
    }

    - (id)initWithCapacity:(NSUInteger)capacity {
    if ((self = [super init])) {
    _dictionary = [[NSMutableDictionary alloc] initWithCapacity:capacity];
    _lock = OS_SPINLOCK_INIT;
    }
    return self;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////
    #pragma mark - NSMutableDictionary

    - (void)setObject:(id)anObject forKey:(id<NSCopying>)aKey {
    OSSpinLockLock(&_lock);
    _dictionary[aKey] = anObject;
    OSSpinLockUnlock(&_lock);
    }

    - (void)removeObjectForKey:(id)aKey {
    OSSpinLockLock(&_lock);
    [_dictionary removeObjectForKey:aKey];
    OSSpinLockUnlock(&_lock);
    }

    - (NSUInteger)count {
    OSSpinLockLock(&_lock);
    NSUInteger count = _dictionary.count;
    OSSpinLockUnlock(&_lock);
    return count;
    }

    - (id)objectForKey:(id)aKey {
    OSSpinLockLock(&_lock);
    id obj = _dictionary[aKey];
    OSSpinLockUnlock(&_lock);
    return obj;
    }

    - (NSEnumerator *)keyEnumerator {
    OSSpinLockLock(&_lock);
    NSEnumerator *keyEnumerator = [_dictionary keyEnumerator];
    OSSpinLockUnlock(&_lock);
    return keyEnumerator;
    }

    @end