Guest User

Untitled

a guest
Feb 19th, 2018
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.14 KB | None | 0 0
  1. #import <Foundation/Foundation.h>
  2. #import <dispatch/dispatch.h>
  3. #import "MAZeroingWeakRef.h"
  4.  
  5. @interface KBMultiDispatchSource : NSObject
  6. {
  7. dispatch_source_t _dispatch;
  8. dispatch_queue_t _queue;
  9. dispatch_source_type_t _type;
  10. CFMutableDictionaryRef _eventObservers;
  11. CFMutableDictionaryRef _cancelObservers;
  12. }
  13.  
  14. - (id) initWithType: (dispatch_source_type_t) type
  15. handle: (uintptr_t) handle
  16. mask: (unsigned long) mask
  17. targetQueue: (dispatch_queue_t) targetQueue;
  18.  
  19. @property (nonatomic, readonly) dispatch_source_type_t type;
  20.  
  21. - (void) resume;
  22. - (void) suspend;
  23. - (void) cancel;
  24. - (BOOL) testCancel;
  25.  
  26. - (uintptr_t) handle;
  27. - (unsigned long) mask;
  28.  
  29. - (void) mergeData: (unsigned long) data;
  30. @property (nonatomic, readonly) unsigned long data;
  31.  
  32. - (void) resetData; // sets data to zero-- builds a new dispatch source behind the scenes
  33.  
  34. - (void) handleEventsForObserver: (id) observer usingBlock: (dispatch_block_t) block;
  35. - (void) handleCancelEventsForObserver: (id) observer usingBlock: (dispatch_block_t) block;
  36. - (void) removeHandlersForObserver: (id) observer;
  37.  
  38. @end
  39.  
  40.  
  41. //
  42. // KBMultiDispatchSource.m
  43. // Kobov3
  44. //
  45. // Created by Jim Dovey on 11-07-07.
  46. // Copyright 2011 Kobo Inc. All rights reserved.
  47. //
  48.  
  49. #import "KBMultiDispatchSource.h"
  50.  
  51. static const void * _CFBlockRetain(CFAllocatorRef allocator, const void * item)
  52. {
  53. return ( Block_copy(item) );
  54. }
  55.  
  56. static void _CFBlockRelease(CFAllocatorRef allocator, const void * item)
  57. {
  58. Block_release(item);
  59. }
  60.  
  61. @implementation KBMultiDispatchSource
  62.  
  63. @synthesize type=_type;
  64.  
  65. + (void) load
  66. {
  67. if ( dispatch_barrier_async == 0 )
  68. return;
  69.  
  70. // switch in the dispatch_barrier_async() versions since they're available
  71.  
  72. Method m1 = class_getInstanceMethod(self, @selector(handleEventsForObserver:usingBlock:));
  73. Method m2 = class_getInstanceMethod(self, @selector(_barrier_handleEventsForObserver:usingBlock:));
  74.  
  75. if ( m1 != NULL && m2 != NULL )
  76. method_exchangeImplementations(m1, m2);
  77.  
  78. m1 = class_getInstanceMethod(self, @selector(handleCancelEventsForObserver:usingBlock:));
  79. m2 = class_getInstanceMethod(self, @selector(_barrier_handleCancelEventsForObserver:usingBlock:));
  80.  
  81. if ( m1 != NULL && m2 != NULL )
  82. method_exchangeImplementations(m1, m2);
  83.  
  84. m1 = class_getInstanceMethod(self, @selector(removeHandlersForObserver:));
  85. m2 = class_getInstanceMethod(self, @selector(_barrier_removeHandlersForObserver:));
  86.  
  87. if ( m1 != NULL && m2 != NULL )
  88. method_exchangeImplementations(m1, m2);
  89. }
  90.  
  91. - (void) _setHandlersForSource: (dispatch_source_t) source
  92. {
  93. {
  94. MAKE_WEAK_SELF();
  95.  
  96. dispatch_source_set_event_handler(source, ^{
  97. USE_WEAK_SELF();
  98.  
  99. NSDictionary * dict = (NSDictionary *)self->_eventObservers;
  100. [dict enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) {
  101. dispatch_block_t block = (dispatch_block_t)obj;
  102. block();
  103. }];
  104. });
  105.  
  106. dispatch_source_set_cancel_handler(source, ^{
  107. USE_WEAK_SELF();
  108.  
  109. NSDictionary * dict = (NSDictionary *)self->_cancelObservers;
  110. [dict enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) {
  111. dispatch_block_t block = (dispatch_block_t)obj;
  112. block();
  113. }];
  114. });
  115. }
  116. }
  117.  
  118. - (id) initWithType: (dispatch_source_type_t) type
  119. handle: (uintptr_t) handle
  120. mask: (unsigned long) mask
  121. targetQueue: (dispatch_queue_t) targetQueue
  122. {
  123. self = [super init];
  124. if ( self == nil )
  125. return ( nil );
  126.  
  127. _dispatch = dispatch_source_create(type, handle, mask, targetQueue);
  128. dispatch_retain(targetQueue);
  129. _queue = targetQueue;
  130. _type = type;
  131.  
  132. CFDictionaryValueCallBacks vcb = {
  133. .version = 0,
  134. .retain = _CFBlockRetain,
  135. .release = _CFBlockRelease,
  136. .copyDescription = NULL,
  137. .equal = NULL
  138. };
  139.  
  140. _eventObservers = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &vcb);
  141. _cancelObservers = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, _eventObservers);
  142. [self _setHandlersForSource: _dispatch];
  143.  
  144. return ( self );
  145. }
  146.  
  147. - (void) dealloc
  148. {
  149. if ( _dispatch != NULL )
  150. dispatch_release(_dispatch);
  151. if ( _queue != NULL )
  152. dispatch_release(_queue);
  153. if ( _eventObservers != NULL )
  154. CFRelease(_eventObservers);
  155. if ( _cancelObservers != NULL )
  156. CFRelease(_cancelObservers);
  157. [super dealloc];
  158. }
  159.  
  160. - (void) resume
  161. {
  162. dispatch_resume(_dispatch);
  163. }
  164.  
  165. - (void) suspend
  166. {
  167. dispatch_suspend(_dispatch);
  168. }
  169.  
  170. - (void) cancel
  171. {
  172. dispatch_source_cancel(_dispatch);
  173. }
  174.  
  175. - (BOOL) testCancel
  176. {
  177. return ( dispatch_source_testcancel(_dispatch) );
  178. }
  179.  
  180. - (uintptr_t) handle
  181. {
  182. return ( dispatch_source_get_handle(_dispatch) );
  183. }
  184.  
  185. - (unsigned long) mask
  186. {
  187. return ( dispatch_source_get_mask(_dispatch) );
  188. }
  189.  
  190. - (void) mergeData: (unsigned long) data
  191. {
  192. dispatch_source_merge_data(_dispatch, data);
  193. }
  194.  
  195. - (unsigned long) data
  196. {
  197. return ( dispatch_source_get_data(_dispatch) );
  198. }
  199.  
  200. - (void) resetData
  201. {
  202. dispatch_source_t newSource = dispatch_source_create(_type, dispatch_source_get_handle(_dispatch), dispatch_source_get_mask(_dispatch), _queue);
  203. [self _setHandlersForSource: newSource];
  204.  
  205. dispatch_release(_dispatch);
  206. _dispatch = newSource;
  207. dispatch_resume(_dispatch);
  208. }
  209.  
  210. - (void) handleEventsForObserver: (id) observer usingBlock: (dispatch_block_t) block
  211. {
  212. MAZeroingWeakRef * weakSelfRef = [MAZeroingWeakRef refWithTarget: self];
  213. dispatch_async(_queue, ^{
  214. MAZeroingWeakRef * observerRef = [MAZeroingWeakRef refWithTarget: observer];
  215. [observerRef setCleanupBlock: ^(id target) {
  216. [[weakSelfRef target] removeHandlersForObserver: target];
  217. }];
  218. CFDictionarySetValue(_eventObservers, observer, block);
  219. });
  220. }
  221.  
  222. - (void) _barrier_handleEventsForObserver: (id) observer usingBlock: (dispatch_block_t) block
  223. {
  224. MAZeroingWeakRef * weakSelfRef = [MAZeroingWeakRef refWithTarget: self];
  225. dispatch_barrier_async(_queue, ^{
  226. MAZeroingWeakRef * observerRef = [MAZeroingWeakRef refWithTarget: observer];
  227. [observerRef setCleanupBlock: ^(id target) {
  228. [[weakSelfRef target] removeHandlersForObserver: target];
  229. }];
  230. CFDictionarySetValue(_eventObservers, observer, block);
  231. });
  232. }
  233.  
  234. - (void) handleCancelEventsForObserver: (id) observer usingBlock: (dispatch_block_t) block
  235. {
  236. MAZeroingWeakRef * weakSelfRef = [MAZeroingWeakRef refWithTarget: self];
  237. dispatch_async(_queue, ^{
  238. MAZeroingWeakRef * observerRef = [MAZeroingWeakRef refWithTarget: observer];
  239. [observerRef setCleanupBlock: ^(id target) {
  240. [[weakSelfRef target] removeHandlersForObserver: target];
  241. }];
  242. CFDictionarySetValue(_cancelObservers, observer, block);
  243. });
  244. }
  245.  
  246. - (void) _barrier_handleCancelEventsForObserver: (id) observer usingBlock: (dispatch_block_t) block
  247. {
  248. MAZeroingWeakRef * weakSelfRef = [MAZeroingWeakRef refWithTarget: self];
  249. dispatch_barrier_async(_queue, ^{
  250. MAZeroingWeakRef * observerRef = [MAZeroingWeakRef refWithTarget: observer];
  251. [observerRef setCleanupBlock: ^(id target) {
  252. [[weakSelfRef target] removeHandlersForObserver: target];
  253. }];
  254. CFDictionarySetValue(_cancelObservers, observer, block);
  255. });
  256. }
  257.  
  258. - (void) removeHandlersForObserver: (id) observer
  259. {
  260. dispatch_async(_queue, ^{
  261. CFDictionaryRemoveValue(_eventObservers, observer);
  262. CFDictionaryRemoveValue(_cancelObservers, observer);
  263. });
  264. }
  265.  
  266. - (void) _barrier_removeHandlersForObserver: (id) observer
  267. {
  268. dispatch_barrier_async(_queue, ^{
  269. CFDictionaryRemoveValue(_eventObservers, observer);
  270. CFDictionaryRemoveValue(_cancelObservers, observer);
  271. });
  272. }
  273.  
  274. @end
Add Comment
Please, Sign In to add comment