Guest User

Untitled

a guest
Jan 22nd, 2018
55
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.47 KB | None | 0 0
  1.  
  2. #import "MVStateStorage.h"
  3.  
  4. @implementation MVStateStorage
  5.  
  6. - (id)init {
  7. self = [super init];
  8. if (self) {
  9. data = [[NSMutableDictionary alloc] init];
  10. queues = [[NSMutableDictionary alloc] init];
  11. }
  12. return self;
  13. }
  14.  
  15. - (void)dealloc {
  16. [queues enumerateKeysAndObjectsUsingBlock:^(id key, NSOperationQueue *obj, BOOL *s) {
  17. [obj cancelAllOperations];
  18. [obj waitUntilAllOperationsAreFinished];
  19. [obj setSuspended:YES];
  20. }];
  21. [queues release];
  22. [data release];
  23. [super dealloc];
  24. }
  25.  
  26. - (NSOperationQueue *)queueForKey:(id)key {
  27. NSOperationQueue *q = [queues objectForKey:key];
  28. if (!q) {
  29. @synchronized(queues) {
  30. q = [[NSOperationQueue alloc] init];
  31. [q setMaxConcurrentOperationCount:1];
  32. [queues setObject:q forKey:key];
  33. [q release];
  34. }
  35. }
  36. return q;
  37. }
  38.  
  39. - (void)cancelOperationsForKey:(id)key {
  40. [[self queueForKey:key] cancelAllOperations];
  41. }
  42.  
  43. - (void)scheduleBlock:(MVStateOpBlock)block forKey:(id)key {
  44. NSOperationQueue *q = [self queueForKey:key];
  45.  
  46. [q addOperationWithBlock:^{
  47. id val = nil;
  48. id res = nil;
  49. @synchronized(data) {
  50. val = [data objectForKey:key];
  51. }
  52.  
  53. NSAutoreleasePool *p = [NSAutoreleasePool new];
  54. res = block(val);
  55. if (val != res) {
  56. if (!res) {
  57. [[NSOperationQueue currentQueue] cancelAllOperations];
  58. @synchronized(data) {
  59. [data removeObjectForKey:key];
  60. }
  61. return;
  62. }
  63. else {
  64. @synchronized(data) {
  65. [data setObject:res forKey:key];
  66. }
  67. }
  68. }
  69. [p release];
  70. }];
  71. }
  72.  
  73. #define PREVENT \
  74. if (preventAccess) {\
  75. [NSException raise:NSInternalInconsistencyException format:@"Setter function called in operation *setup* block."];\
  76. }
  77.  
  78. - (void)setupOperationForKey:(id)key withBlock:(MVOpSetupBlock)block {
  79. NSOperationQueue *q = [self queueForKey:key];
  80.  
  81. __block BOOL preventAccess = YES;
  82. __block id cachedVal = nil;
  83. MVGetterBlock getter = ^{
  84. PREVENT
  85. if (cachedVal) return cachedVal;
  86. @synchronized(data) {
  87. return [data objectForKey:key];
  88. }
  89. };
  90. MVSetterBlock setter = ^(id newVal) {
  91. PREVENT
  92. @synchronized(data) {
  93. cachedVal = newVal;
  94. [data setObject:newVal forKey:key];
  95. }
  96. };
  97.  
  98. NSAutoreleasePool *p = [NSAutoreleasePool new];
  99. NSOperation *op = block(getter, setter);
  100. preventAccess = NO;
  101. cachedVal = nil;
  102. [q addOperation:op];
  103. [p release];
  104. }
  105.  
  106. #undef PREVENT
  107.  
  108. - (NSDictionary *)dictionaryRepresentation {
  109. @synchronized(data) {
  110. return [[[NSDictionary alloc] initWithDictionary:data copyItems:YES] autorelease];
  111. }
  112. }
  113.  
  114. - (NSArray *)allKeys {
  115. @synchronized(data) {
  116. return [[[data allKeys] copy] autorelease];
  117. }
  118. }
  119.  
  120. @end
Add Comment
Please, Sign In to add comment