Skip to content

Commit b4c741a

Browse files
committed
Change the SDCallbackQueue to allows easier usage. Only main queue use SafeAsyncMainQueue, others revert back to default value
The implementation don't need complicated check, using object compare is enough
1 parent 2f39f8a commit b4c741a

File tree

2 files changed

+25
-44
lines changed

2 files changed

+25
-44
lines changed

SDWebImage/Core/SDCallbackQueue.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,24 @@ typedef NS_ENUM(NSUInteger, SDCallbackPolicy) {
2727
/// Useful when you call SDWebImage in non-main queue and want to avoid it callback into main queue, which may cause issue.
2828
@interface SDCallbackQueue : NSObject
2929

30-
/// The shared main queue. This is the default value, has the same effect when passing `nil` to `SDWebImageContextCallbackQueue`
30+
/// The main queue. This is the default value, has the same effect when passing `nil` to `SDWebImageContextCallbackQueue`
31+
/// The policy defaults to `SDCallbackPolicySafeAsyncMainQueue`
3132
@property (nonnull, class, readonly) SDCallbackQueue *mainQueue;
3233

3334
/// The caller current queue. Using `dispatch_get_current_queue`. This is not a dynamic value and only keep the first call time queue.
35+
/// The policy defaults to `SDCallbackPolicySafeExecute`
3436
@property (nonnull, class, readonly) SDCallbackQueue *currentQueue;
3537

3638
/// The global concurrent queue (user-initiated QoS). Using `dispatch_get_global_queue`.
39+
/// The policy defaults to `SDCallbackPolicySafeExecute`
3740
@property (nonnull, class, readonly) SDCallbackQueue *globalQueue;
3841

3942
/// The current queue's callback policy.
40-
/// defaults to `SDCallbackPolicySafeAsyncMainQueue` from v5.20.1, which behaves like the old macro `dispatch_main_async_safe`
41-
/// @note old 5.x version use `SDCallbackPolicySafeExecute`, which may behave incorrectly when you sync the block into global queue.
42-
@property (assign, readwrite) SDCallbackPolicy policy;
43+
@property (nonatomic, assign, readwrite) SDCallbackPolicy policy;
4344

4445
- (nonnull instancetype)init NS_UNAVAILABLE;
4546
+ (nonnull instancetype)new NS_UNAVAILABLE;
46-
/// Create the callback queue with a GCD queue
47+
/// Create the callback queue with a GCD queue. The policy defaults to `SDCallbackPolicySafeExecute`
4748
/// - Parameter queue: The GCD queue, should not be NULL
4849
- (nonnull instancetype)initWithDispatchQueue:(nonnull dispatch_queue_t)queue NS_DESIGNATED_INITIALIZER;
4950

SDWebImage/Core/SDCallbackQueue.m

Lines changed: 19 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,9 @@
1212
@interface SDCallbackQueue ()
1313

1414
@property (nonatomic, strong, nonnull) dispatch_queue_t queue;
15-
@property (nonatomic, strong, nonnull) NSThread *thread;
1615

1716
@end
1817

19-
static void * SDCallbackQueueKey = &SDCallbackQueueKey;
20-
static void SDReleaseBlock(void *context) {
21-
CFRelease(context);
22-
}
23-
2418
static inline void SDSafeMainQueueAsync(dispatch_block_t _Nonnull block) {
2519
if (NSThread.isMainThread) {
2620
// Match exists `dispatch_main_async_safe` behavior
@@ -42,26 +36,19 @@ static inline void SDSafeMainThreadAsync(dispatch_block_t _Nonnull block) {
4236
}
4337
}
4438

45-
static void SDSafeExecute(SDCallbackQueue *callbackQueue, dispatch_block_t _Nonnull block, BOOL async) {
46-
// Extend gcd queue's life cycle
47-
dispatch_queue_t queue = callbackQueue.queue;
48-
// Special handle for main queue label only (custom queue can have the same label)
49-
const char *label = dispatch_queue_get_label(queue);
50-
if (label && label == dispatch_queue_get_label(dispatch_get_main_queue())) {
51-
const char *currentLabel = dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL);
52-
if (label == currentLabel) {
53-
block();
54-
return;
55-
}
39+
static void SDSafeExecute(dispatch_queue_t queue, dispatch_block_t _Nonnull block, BOOL async) {
40+
#pragma clang diagnostic push
41+
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
42+
dispatch_queue_t currentQueue = dispatch_get_current_queue();
43+
#pragma clang diagnostic pop
44+
if (queue == currentQueue) {
45+
block();
46+
return;
5647
}
57-
// Check specific to detect queue equal
58-
void *specific = dispatch_queue_get_specific(queue, SDCallbackQueueKey);
59-
if (specific && CFGetTypeID(specific) == CFUUIDGetTypeID()) {
60-
void *currentSpecific = dispatch_get_specific(SDCallbackQueueKey);
61-
if (currentSpecific && CFGetTypeID(currentSpecific) == CFUUIDGetTypeID() && CFEqual(specific, currentSpecific)) {
62-
block();
63-
return;
64-
}
48+
// Special handle for main queue only
49+
if (NSThread.isMainThread && queue == dispatch_get_main_queue()) {
50+
block();
51+
return;
6552
}
6653
if (async) {
6754
dispatch_async(queue, block);
@@ -76,22 +63,15 @@ - (instancetype)initWithDispatchQueue:(dispatch_queue_t)queue {
7663
self = [super init];
7764
if (self) {
7865
NSCParameterAssert(queue);
79-
CFUUIDRef UUID = CFUUIDCreate(kCFAllocatorDefault);
80-
dispatch_queue_set_specific(queue, SDCallbackQueueKey, (void *)UUID, SDReleaseBlock);
8166
_queue = queue;
82-
_policy = SDCallbackPolicySafeAsyncMainQueue;
83-
// global queue can execute on main thread, like call `dispatch_sync(globalQueue)` in main thread
84-
_thread = NSThread.currentThread;
67+
_policy = SDCallbackPolicySafeExecute;
8568
}
8669
return self;
8770
}
8871

8972
+ (SDCallbackQueue *)mainQueue {
90-
static dispatch_once_t onceToken;
91-
static SDCallbackQueue *queue;
92-
dispatch_once(&onceToken, ^{
93-
queue = [[SDCallbackQueue alloc] initWithDispatchQueue:dispatch_get_main_queue()];
94-
});
73+
SDCallbackQueue *queue = [[SDCallbackQueue alloc] initWithDispatchQueue:dispatch_get_main_queue()];
74+
queue->_policy = SDCallbackPolicySafeAsyncMainQueue;
9575
return queue;
9676
}
9777

@@ -111,7 +91,7 @@ + (SDCallbackQueue *)globalQueue {
11191
- (void)sync:(nonnull dispatch_block_t)block {
11292
switch (self.policy) {
11393
case SDCallbackPolicySafeExecute:
114-
SDSafeExecute(self, block, NO);
94+
SDSafeExecute(self.queue, block, NO);
11595
break;
11696
case SDCallbackPolicyDispatch:
11797
dispatch_sync(self.queue, block);
@@ -126,15 +106,15 @@ - (void)sync:(nonnull dispatch_block_t)block {
126106
SDSafeMainThreadAsync(block);
127107
break;
128108
default:
129-
SDSafeExecute(self, block, NO);
109+
NSCAssert(NO, @"unexpected policy %tu", self.policy);
130110
break;
131111
}
132112
}
133113

134114
- (void)async:(nonnull dispatch_block_t)block {
135115
switch (self.policy) {
136116
case SDCallbackPolicySafeExecute:
137-
SDSafeExecute(self, block, YES);
117+
SDSafeExecute(self.queue, block, YES);
138118
break;
139119
case SDCallbackPolicyDispatch:
140120
dispatch_async(self.queue, block);
@@ -149,7 +129,7 @@ - (void)async:(nonnull dispatch_block_t)block {
149129
SDSafeMainThreadAsync(block);
150130
break;
151131
default:
152-
SDSafeExecute(self, block, YES);
132+
NSCAssert(NO, @"unexpected policy %tu", self.policy);
153133
break;
154134
}
155135
}

0 commit comments

Comments
 (0)