Skip to content

Commit 2f39f8a

Browse files
committed
Introduce SafeAsyncMainThread policy
This used for user who really need `mainThread` but not `mainQueue`
1 parent ed1f0f8 commit 2f39f8a

File tree

2 files changed

+27
-9
lines changed

2 files changed

+27
-9
lines changed

SDWebImage/Core/SDCallbackQueue.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ typedef NS_ENUM(NSUInteger, SDCallbackPolicy) {
1717
SDCallbackPolicyDispatch = 1,
1818
/// Ignore any async/sync and just directly invoke `block` in current queue (without `dispatch_async`/`dispatch_sync`)
1919
SDCallbackPolicyInvoke = 2,
20-
/// Ensure callback in main queue and main thread, will do `dispatch_async` if the current queue is not main queue; else do invoke `block`. Never use `dispatch_sync`, suitable for UI-related work
21-
SDCallbackPolicyMainAsyncSafe = 3
20+
/// Ensure callback in main queue (no gurantee on main thread). Do `dispatch_async` if the current queue is not main queue; else do invoke `block`. Never use `dispatch_sync`, suitable for general UI-related code
21+
SDCallbackPolicySafeAsyncMainQueue = 3,
22+
/// Ensure callback in main thread. Do `dispatch_async` if the `NSThread.isMainTrhead == true` ; else do invoke `block`. Never use `dispatch_sync`, suitable for special UI-related code
23+
SDCallbackPolicySafeAsyncMainThread = 4,
2224
};
2325

2426
/// SDCallbackQueue is a wrapper used to control how the completionBlock should perform on queues, used by our `Cache`/`Manager`/`Loader`.
@@ -34,7 +36,9 @@ typedef NS_ENUM(NSUInteger, SDCallbackPolicy) {
3436
/// The global concurrent queue (user-initiated QoS). Using `dispatch_get_global_queue`.
3537
@property (nonnull, class, readonly) SDCallbackQueue *globalQueue;
3638

37-
/// The current queue's callback policy, defaults to `SDCallbackPolicyMainAsyncSafe`, which behaves like the old macro `dispatch_main_async_safe`
39+
/// 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.
3842
@property (assign, readwrite) SDCallbackPolicy policy;
3943

4044
- (nonnull instancetype)init NS_UNAVAILABLE;

SDWebImage/Core/SDCallbackQueue.m

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ static void SDReleaseBlock(void *context) {
2121
CFRelease(context);
2222
}
2323

24-
static inline void SDSafeMainAsync(dispatch_block_t _Nonnull block) {
24+
static inline void SDSafeMainQueueAsync(dispatch_block_t _Nonnull block) {
2525
if (NSThread.isMainThread) {
2626
// Match exists `dispatch_main_async_safe` behavior
2727
const char *currentLabel = dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL);
@@ -34,6 +34,14 @@ static inline void SDSafeMainAsync(dispatch_block_t _Nonnull block) {
3434
dispatch_async(dispatch_get_main_queue(), block);
3535
}
3636

37+
static inline void SDSafeMainThreadAsync(dispatch_block_t _Nonnull block) {
38+
if (NSThread.isMainThread) {
39+
block();
40+
} else {
41+
dispatch_async(dispatch_get_main_queue(), block);
42+
}
43+
}
44+
3745
static void SDSafeExecute(SDCallbackQueue *callbackQueue, dispatch_block_t _Nonnull block, BOOL async) {
3846
// Extend gcd queue's life cycle
3947
dispatch_queue_t queue = callbackQueue.queue;
@@ -71,7 +79,7 @@ - (instancetype)initWithDispatchQueue:(dispatch_queue_t)queue {
7179
CFUUIDRef UUID = CFUUIDCreate(kCFAllocatorDefault);
7280
dispatch_queue_set_specific(queue, SDCallbackQueueKey, (void *)UUID, SDReleaseBlock);
7381
_queue = queue;
74-
_policy = SDCallbackPolicyMainAsyncSafe;
82+
_policy = SDCallbackPolicySafeAsyncMainQueue;
7583
// global queue can execute on main thread, like call `dispatch_sync(globalQueue)` in main thread
7684
_thread = NSThread.currentThread;
7785
}
@@ -111,8 +119,11 @@ - (void)sync:(nonnull dispatch_block_t)block {
111119
case SDCallbackPolicyInvoke:
112120
block();
113121
break;
114-
case SDCallbackPolicyMainAsyncSafe:
115-
SDSafeMainAsync(block);
122+
case SDCallbackPolicySafeAsyncMainQueue:
123+
SDSafeMainQueueAsync(block);
124+
break;
125+
case SDCallbackPolicySafeAsyncMainThread:
126+
SDSafeMainThreadAsync(block);
116127
break;
117128
default:
118129
SDSafeExecute(self, block, NO);
@@ -131,8 +142,11 @@ - (void)async:(nonnull dispatch_block_t)block {
131142
case SDCallbackPolicyInvoke:
132143
block();
133144
break;
134-
case SDCallbackPolicyMainAsyncSafe:
135-
SDSafeMainAsync(block);
145+
case SDCallbackPolicySafeAsyncMainQueue:
146+
SDSafeMainQueueAsync(block);
147+
break;
148+
case SDCallbackPolicySafeAsyncMainThread:
149+
SDSafeMainThreadAsync(block);
136150
break;
137151
default:
138152
SDSafeExecute(self, block, YES);

0 commit comments

Comments
 (0)