ATUnitySafeThreadDictionary.m 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. // ATSafeThreadDictionary.h
  2. // ATSDK
  3. //
  4. // Created by topon on 2020/9/21.
  5. // Copyright © 2020 AnyThink. All rights reserved.
  6. //
  7. #import "ATUnitySafeThreadDictionary.h"
  8. #import <pthread.h>
  9. #define INIT(...) self = super.init; \
  10. if (!self) return nil; \
  11. __VA_ARGS__; \
  12. if (!_dic) return nil; \
  13. [self __initMutex:&_mutex_lock];\
  14. return self;
  15. #define LOCK(...) pthread_mutex_lock(&_mutex_lock); \
  16. __VA_ARGS__; \
  17. pthread_mutex_unlock(&_mutex_lock);
  18. @implementation ATUnitySafeThreadDictionary {
  19. NSMutableDictionary *_dic; //Subclass a class cluster...
  20. pthread_mutex_t _mutex_lock;
  21. pthread_mutexattr_t _attr;
  22. }
  23. #pragma mark - init
  24. - (void)__initMutex:(pthread_mutex_t *)mutex {
  25. // 递归锁:允许同一个线程对一把锁进行重复加锁
  26. // 初始化属性
  27. pthread_mutexattr_init(&_attr);
  28. pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_RECURSIVE);
  29. // 初始化锁
  30. pthread_mutex_init(mutex, &_attr);
  31. }
  32. - (instancetype)init {
  33. INIT(_dic = [[NSMutableDictionary alloc] init]);
  34. }
  35. - (instancetype)initWithObjects:(NSArray *)objects forKeys:(NSArray *)keys {
  36. INIT(_dic = [[NSMutableDictionary alloc] initWithObjects:objects forKeys:keys]);
  37. }
  38. - (instancetype)initWithCapacity:(NSUInteger)capacity {
  39. INIT(_dic = [[NSMutableDictionary alloc] initWithCapacity:capacity]);
  40. }
  41. - (instancetype)initWithObjects:(const id[])objects forKeys:(const id <NSCopying>[])keys count:(NSUInteger)cnt {
  42. INIT(_dic = [[NSMutableDictionary alloc] initWithObjects:objects forKeys:keys count:cnt]);
  43. }
  44. - (instancetype)initWithDictionary:(NSDictionary *)otherDictionary {
  45. INIT(_dic = [[NSMutableDictionary alloc] initWithDictionary:otherDictionary]);
  46. }
  47. - (instancetype)initWithDictionary:(NSDictionary *)otherDictionary copyItems:(BOOL)flag {
  48. INIT(_dic = [[NSMutableDictionary alloc] initWithDictionary:otherDictionary copyItems:flag]);
  49. }
  50. #pragma mark - method
  51. - (NSUInteger)count {
  52. LOCK(NSUInteger c = _dic.count); return c;
  53. }
  54. - (id)objectForKey:(id)aKey {
  55. LOCK(id o = [_dic objectForKey:aKey]); return o;
  56. }
  57. - (NSEnumerator *)keyEnumerator {
  58. LOCK(NSEnumerator * e = [_dic keyEnumerator]); return e;
  59. }
  60. - (NSArray *)allKeys {
  61. LOCK(NSArray * a = [_dic allKeys]); return a;
  62. }
  63. - (NSArray *)allKeysForObject:(id)anObject {
  64. LOCK(NSArray * a = [_dic allKeysForObject:anObject]); return a;
  65. }
  66. - (NSArray *)allValues {
  67. LOCK(NSArray * a = [_dic allValues]); return a;
  68. }
  69. - (NSString *)description {
  70. LOCK(NSString * d = [_dic description]); return d;
  71. }
  72. - (NSString *)descriptionInStringsFileFormat {
  73. LOCK(NSString * d = [_dic descriptionInStringsFileFormat]); return d;
  74. }
  75. - (NSString *)descriptionWithLocale:(id)locale {
  76. LOCK(NSString * d = [_dic descriptionWithLocale:locale]); return d;
  77. }
  78. - (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level {
  79. LOCK(NSString * d = [_dic descriptionWithLocale:locale indent:level]); return d;
  80. }
  81. - (BOOL)isEqualToDictionary:(NSDictionary *)otherDictionary {
  82. if (otherDictionary == self) return YES;
  83. if ([otherDictionary isKindOfClass:ATUnitySafeThreadDictionary.class]) {
  84. ATUnitySafeThreadDictionary *other = (id)otherDictionary;
  85. BOOL isEqual;
  86. pthread_mutex_lock(&_mutex_lock);
  87. pthread_mutex_lock(&(other->_mutex_lock));
  88. isEqual = [_dic isEqual:other->_dic];
  89. pthread_mutex_unlock(&_mutex_lock);
  90. pthread_mutex_unlock(&(other->_mutex_lock));
  91. return isEqual;
  92. }
  93. return NO;
  94. }
  95. - (NSEnumerator *)objectEnumerator {
  96. LOCK(NSEnumerator * e = [_dic objectEnumerator]); return e;
  97. }
  98. - (NSArray *)objectsForKeys:(NSArray *)keys notFoundMarker:(id)marker {
  99. LOCK(NSArray * a = [_dic objectsForKeys:keys notFoundMarker:marker]); return a;
  100. }
  101. - (NSArray *)keysSortedByValueUsingSelector:(SEL)comparator {
  102. LOCK(NSArray * a = [_dic keysSortedByValueUsingSelector:comparator]); return a;
  103. }
  104. - (void)getObjects:(id __unsafe_unretained[])objects andKeys:(id __unsafe_unretained[])keys {
  105. LOCK([_dic getObjects:objects andKeys:keys]);
  106. }
  107. - (id)objectForKeyedSubscript:(id)key {
  108. LOCK(id o = [_dic objectForKeyedSubscript:key]); return o;
  109. }
  110. - (void)enumerateKeysAndObjectsUsingBlock:(__attribute__((noescape)) void (^)(id key, id obj, BOOL *stop))block {
  111. LOCK([_dic enumerateKeysAndObjectsUsingBlock:block]);
  112. }
  113. - (void)enumerateKeysAndObjectsWithOptions:(NSEnumerationOptions)opts usingBlock:(__attribute__((noescape)) void (^)(id key, id obj, BOOL *stop))block {
  114. LOCK([_dic enumerateKeysAndObjectsWithOptions:opts usingBlock:block]);
  115. }
  116. - (NSArray *)keysSortedByValueUsingComparator:(__attribute__((noescape)) NSComparator)cmptr {
  117. LOCK(NSArray * a = [_dic keysSortedByValueUsingComparator:cmptr]); return a;
  118. }
  119. - (NSArray *)keysSortedByValueWithOptions:(NSSortOptions)opts usingComparator:(__attribute__((noescape)) NSComparator)cmptr {
  120. LOCK(NSArray * a = [_dic keysSortedByValueWithOptions:opts usingComparator:cmptr]); return a;
  121. }
  122. - (NSSet *)keysOfEntriesPassingTest:(__attribute__((noescape)) BOOL (^)(id key, id obj, BOOL *stop))predicate {
  123. LOCK(NSSet * a = [_dic keysOfEntriesPassingTest:predicate]); return a;
  124. }
  125. - (NSSet *)keysOfEntriesWithOptions:(NSEnumerationOptions)opts passingTest:(__attribute__((noescape)) BOOL (^)(id key, id obj, BOOL *stop))predicate {
  126. LOCK(NSSet * a = [_dic keysOfEntriesWithOptions:opts passingTest:predicate]); return a;
  127. }
  128. #pragma mark - mutable
  129. - (void)removeObjectForKey:(id)aKey {
  130. LOCK(
  131. if (aKey) {
  132. [_dic removeObjectForKey:aKey];
  133. });
  134. }
  135. - (void)setObject:(id)anObject forKey:(id <NSCopying> )aKey {
  136. LOCK(
  137. if (anObject && aKey) {
  138. [_dic setObject:anObject forKey:aKey];
  139. });
  140. }
  141. - (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary {
  142. LOCK(
  143. if (otherDictionary) {
  144. [_dic addEntriesFromDictionary:otherDictionary];
  145. });
  146. }
  147. - (void)removeAllObjects {
  148. LOCK([_dic removeAllObjects]);
  149. }
  150. - (void)removeObjectsForKeys:(NSArray *)keyArray {
  151. LOCK([_dic removeObjectsForKeys:keyArray]);
  152. }
  153. - (void)setDictionary:(NSDictionary *)otherDictionary {
  154. LOCK(
  155. if (otherDictionary) {
  156. [_dic setDictionary:otherDictionary];
  157. });
  158. }
  159. - (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying> )key {
  160. LOCK(
  161. if (obj && key) {
  162. [_dic setObject:obj forKeyedSubscript:key];
  163. });
  164. }
  165. #pragma mark - protocol
  166. - (id)copyWithZone:(NSZone *)zone {
  167. return [self mutableCopyWithZone:zone];
  168. }
  169. - (id)mutableCopyWithZone:(NSZone *)zone {
  170. LOCK(id copiedDictionary = [[self.class allocWithZone:zone] initWithDictionary:_dic]);
  171. return copiedDictionary;
  172. }
  173. - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
  174. objects:(id __unsafe_unretained[])stackbuf
  175. count:(NSUInteger)len {
  176. LOCK(NSUInteger count = [_dic countByEnumeratingWithState:state objects:stackbuf count:len]);
  177. return count;
  178. }
  179. - (BOOL)isEqual:(id)object {
  180. if (object == self) return YES;
  181. if ([object isKindOfClass:ATUnitySafeThreadDictionary.class]) {
  182. ATUnitySafeThreadDictionary *other = object;
  183. BOOL isEqual;
  184. pthread_mutex_lock(&_mutex_lock);
  185. pthread_mutex_lock(&(other->_mutex_lock));
  186. isEqual = [_dic isEqual:other->_dic];
  187. pthread_mutex_unlock(&_mutex_lock);
  188. pthread_mutex_unlock(&(other->_mutex_lock));
  189. return isEqual;
  190. }
  191. return NO;
  192. }
  193. - (NSUInteger)hash {
  194. LOCK(NSUInteger hash = [_dic hash]);
  195. return hash;
  196. }
  197. - (void)dealloc {
  198. pthread_mutex_destroy(&_mutex_lock);
  199. pthread_mutexattr_destroy(&_attr);
  200. }
  201. @end