Introduce SafeAsyncMainThread policy

This used for user who really need `mainThread` but not `mainQueue`
This commit is contained in:
DreamPiggy
2024-11-14 17:10:38 +08:00
parent ed1f0f8218
commit 2f39f8aea6
2 changed files with 27 additions and 9 deletions
+7 -3
View File
@@ -17,8 +17,10 @@ typedef NS_ENUM(NSUInteger, SDCallbackPolicy) {
SDCallbackPolicyDispatch = 1,
/// Ignore any async/sync and just directly invoke `block` in current queue (without `dispatch_async`/`dispatch_sync`)
SDCallbackPolicyInvoke = 2,
/// 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
SDCallbackPolicyMainAsyncSafe = 3
/// 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
SDCallbackPolicySafeAsyncMainQueue = 3,
/// 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
SDCallbackPolicySafeAsyncMainThread = 4,
};
/// 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) {
/// The global concurrent queue (user-initiated QoS). Using `dispatch_get_global_queue`.
@property (nonnull, class, readonly) SDCallbackQueue *globalQueue;
/// The current queue's callback policy, defaults to `SDCallbackPolicyMainAsyncSafe`, which behaves like the old macro `dispatch_main_async_safe`
/// The current queue's callback policy.
/// defaults to `SDCallbackPolicySafeAsyncMainQueue` from v5.20.1, which behaves like the old macro `dispatch_main_async_safe`
/// @note old 5.x version use `SDCallbackPolicySafeExecute`, which may behave incorrectly when you sync the block into global queue.
@property (assign, readwrite) SDCallbackPolicy policy;
- (nonnull instancetype)init NS_UNAVAILABLE;
+20 -6
View File
@@ -21,7 +21,7 @@ static void SDReleaseBlock(void *context) {
CFRelease(context);
}
static inline void SDSafeMainAsync(dispatch_block_t _Nonnull block) {
static inline void SDSafeMainQueueAsync(dispatch_block_t _Nonnull block) {
if (NSThread.isMainThread) {
// Match exists `dispatch_main_async_safe` behavior
const char *currentLabel = dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL);
@@ -34,6 +34,14 @@ static inline void SDSafeMainAsync(dispatch_block_t _Nonnull block) {
dispatch_async(dispatch_get_main_queue(), block);
}
static inline void SDSafeMainThreadAsync(dispatch_block_t _Nonnull block) {
if (NSThread.isMainThread) {
block();
} else {
dispatch_async(dispatch_get_main_queue(), block);
}
}
static void SDSafeExecute(SDCallbackQueue *callbackQueue, dispatch_block_t _Nonnull block, BOOL async) {
// Extend gcd queue's life cycle
dispatch_queue_t queue = callbackQueue.queue;
@@ -71,7 +79,7 @@ static void SDSafeExecute(SDCallbackQueue *callbackQueue, dispatch_block_t _Nonn
CFUUIDRef UUID = CFUUIDCreate(kCFAllocatorDefault);
dispatch_queue_set_specific(queue, SDCallbackQueueKey, (void *)UUID, SDReleaseBlock);
_queue = queue;
_policy = SDCallbackPolicyMainAsyncSafe;
_policy = SDCallbackPolicySafeAsyncMainQueue;
// global queue can execute on main thread, like call `dispatch_sync(globalQueue)` in main thread
_thread = NSThread.currentThread;
}
@@ -111,8 +119,11 @@ static void SDSafeExecute(SDCallbackQueue *callbackQueue, dispatch_block_t _Nonn
case SDCallbackPolicyInvoke:
block();
break;
case SDCallbackPolicyMainAsyncSafe:
SDSafeMainAsync(block);
case SDCallbackPolicySafeAsyncMainQueue:
SDSafeMainQueueAsync(block);
break;
case SDCallbackPolicySafeAsyncMainThread:
SDSafeMainThreadAsync(block);
break;
default:
SDSafeExecute(self, block, NO);
@@ -131,8 +142,11 @@ static void SDSafeExecute(SDCallbackQueue *callbackQueue, dispatch_block_t _Nonn
case SDCallbackPolicyInvoke:
block();
break;
case SDCallbackPolicyMainAsyncSafe:
SDSafeMainAsync(block);
case SDCallbackPolicySafeAsyncMainQueue:
SDSafeMainQueueAsync(block);
break;
case SDCallbackPolicySafeAsyncMainThread:
SDSafeMainThreadAsync(block);
break;
default:
SDSafeExecute(self, block, YES);