Repository: SDWebImage/SDWebImage
File: SDWebImage/Core/SDCallbackQueue.h (C/C++)

Code before:
/*
 * This file is part of the SDWebImage package.
 * (c) Olivier Poitrey <rs@dailymotion.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */


#import "SDWebImageCompat.h"

/// SDCallbackPolicy controls how we execute the block on the queue, like whether to use `dispatch_async/dispatch_sync`, check if current queue match target queue, or just invoke without any context.
typedef NS_ENUM(NSUInteger, SDCallbackPolicy) {
    /// When the current queue is equal to callback queue, sync/async will just invoke `block` directly without dispatch. Else it use `dispatch_async`/`dispatch_sync` to dispatch block on queue. This is useful for UIKit rendering to ensure all blocks executed in the same runloop
    SDCallbackPolicySafeExecute = 0,
    /// Follow async/sync using the correspond `dispatch_async`/`dispatch_sync` to dispatch block on queue
    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 (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`.
/// Useful when you call SDWebImage in non-main queue and want to avoid it callback into main queue, which may cause issue.
@interface SDCallbackQueue : NSObject

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

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

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

/// The current queue's callback policy.
@property (nonatomic, assign, readwrite) SDCallbackPolicy policy;

- (nonnull instancetype)init NS_UNAVAILABLE;

Review comment (suggestion):
Seems the comment is not correct. The code implementation shows “When current thread is not main thread, do dispatch_async”

TODO: fix later @dreampiggy 

Code after:
/*
 * This file is part of the SDWebImage package.
 * (c) Olivier Poitrey <rs@dailymotion.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */


#import "SDWebImageCompat.h"

/// SDCallbackPolicy controls how we execute the block on the queue, like whether to use `dispatch_async/dispatch_sync`, check if current queue match target queue, or just invoke without any context.
typedef NS_ENUM(NSUInteger, SDCallbackPolicy) {
    /// When the current queue is equal to callback queue, sync/async will just invoke `block` directly without dispatch. Else it use `dispatch_async`/`dispatch_sync` to dispatch block on queue. This is useful for UIKit rendering to ensure all blocks executed in the same runloop
    SDCallbackPolicySafeExecute = 0,
    /// Follow async/sync using the correspond `dispatch_async`/`dispatch_sync` to dispatch block on queue
    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 thread. Do `dispatch_async` if the `NSThread.isMainTrhead == true` ; else do invoke `block`. Never use `dispatch_sync`, suitable for special UI-related code
    SDCallbackPolicySafeAsyncMainThread = 3,
};

/// SDCallbackQueue is a wrapper used to control how the completionBlock should perform on queues, used by our `Cache`/`Manager`/`Loader`.
/// Useful when you call SDWebImage in non-main queue and want to avoid it callback into main queue, which may cause issue.
@interface SDCallbackQueue : NSObject

/// The main queue. This is the default value, has the same effect when passing `nil` to `SDWebImageContextCallbackQueue`
/// The policy defaults to `SDCallbackPolicySafeAsyncMainThread`
@property (nonnull, class, readonly) SDCallbackQueue *mainQueue;

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

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

/// The current queue's callback policy.
@property (nonatomic, assign, readwrite) SDCallbackPolicy policy;

- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)new  NS_UNAVAILABLE;
/// Create the callback queue with a GCD queue. The policy defaults to `SDCallbackPolicySafeExecute`