Skip to content

Instantly share code, notes, and snippets.

@rnapier rnapier/main.m
Last active Apr 5, 2019

Embed
What would you like to do?
GCD accessor
//
// main.m
// test
//
// Created by Rob Napier on 4/5/19.
//
#import <Foundation/Foundation.h>
@interface MyClass: NSObject
@property (nonatomic, readwrite, copy) NSString *name;
@end
@interface MyClass()
// I often just use one queue for the whole object, but you can also
// split things out so each property has its own queue.
@property (nonatomic, readwrite, strong) dispatch_queue_t queue;
@end
@implementation MyClass {
NSString *_name; // Make a backing ivar
}
- (instancetype)init
{
self = [super init];
if (self) {
// Standard concurrent queue
_queue = dispatch_queue_create("MyClass", DISPATCH_QUEUE_CONCURRENT);
}
return self;
}
- (NSString *)name {
// We have to block here (_sync), but since this is concurrent we will only
// be blocked if there's a write queued up.
__block NSString *result;
dispatch_sync(self.queue, ^{
result = self->_name;
});
return result;
}
- (void)setName:(NSString *)name {
// Barrier says that this block can't start until all previous blocks have finished
// and no later blocks may start until this block is done. Make it fast. That's why
// we do the copy before going into the barrier.
// All reads that were submitted before this write will see the old value, and all
// reads that were submitted after this write will see the new value.
NSString *copy = [name copy];
dispatch_barrier_async(self.queue, ^{
self->_name = copy;
});
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
MyClass *x = [MyClass new];
x.name = @"Alice";
NSLog(@"Hello, %@!", x.name);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.