提交
This commit is contained in:
26
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSBolts.h
generated
Normal file
26
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSBolts.h
generated
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#import "OSSCancellationToken.h"
|
||||
#import "OSSCancellationTokenRegistration.h"
|
||||
#import "OSSCancellationTokenSource.h"
|
||||
#import "OSSExecutor.h"
|
||||
#import "OSSTask.h"
|
||||
#import "OSSTaskCompletionSource.h"
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
A string containing the version of the Bolts Framework used by the current application.
|
||||
*/
|
||||
extern NSString *const OSSBoltsFrameworkVersionString;
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
17
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSBolts.m
generated
Normal file
17
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSBolts.m
generated
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#import "OSSBolts.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NSString *const OSSBoltsFrameworkVersionString = @"1.7.0";
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
42
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSCancellationToken.h
generated
Normal file
42
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSCancellationToken.h
generated
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "OSSCancellationTokenRegistration.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/*!
|
||||
A block that will be called when a token is cancelled.
|
||||
*/
|
||||
typedef void(^OSSCancellationBlock)(void);
|
||||
|
||||
/*!
|
||||
The consumer view of a CancellationToken.
|
||||
Propagates notification that operations should be canceled.
|
||||
A OSSCancellationToken has methods to inspect whether the token has been cancelled.
|
||||
*/
|
||||
@interface OSSCancellationToken : NSObject
|
||||
|
||||
/*!
|
||||
Whether cancellation has been requested for this token source.
|
||||
*/
|
||||
@property (nonatomic, assign, readonly, getter=isCancellationRequested) BOOL cancellationRequested;
|
||||
|
||||
/*!
|
||||
Register a block to be notified when the token is cancelled.
|
||||
If the token is already cancelled the delegate will be notified immediately.
|
||||
*/
|
||||
- (OSSCancellationTokenRegistration *)registerCancellationObserverWithBlock:(OSSCancellationBlock)block;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
144
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSCancellationToken.m
generated
Normal file
144
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSCancellationToken.m
generated
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#import "OSSCancellationToken.h"
|
||||
#import "OSSCancellationTokenRegistration.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OSSCancellationToken ()
|
||||
|
||||
@property (nullable, nonatomic, strong) NSMutableArray *registrations;
|
||||
@property (nonatomic, strong) NSObject *lock;
|
||||
@property (nonatomic) BOOL disposed;
|
||||
|
||||
@end
|
||||
|
||||
@interface OSSCancellationTokenRegistration (OSSCancellationToken)
|
||||
|
||||
+ (instancetype)registrationWithToken:(OSSCancellationToken *)token delegate:(OSSCancellationBlock)delegate;
|
||||
|
||||
- (void)notifyDelegate;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OSSCancellationToken
|
||||
|
||||
@synthesize cancellationRequested = _cancellationRequested;
|
||||
|
||||
#pragma mark - Initializer
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (!self) return self;
|
||||
|
||||
_registrations = [NSMutableArray array];
|
||||
_lock = [NSObject new];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Custom Setters/Getters
|
||||
|
||||
- (BOOL)isCancellationRequested {
|
||||
@synchronized(self.lock) {
|
||||
[self throwIfDisposed];
|
||||
return _cancellationRequested;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)cancel {
|
||||
NSArray *registrations;
|
||||
@synchronized(self.lock) {
|
||||
[self throwIfDisposed];
|
||||
if (_cancellationRequested) {
|
||||
return;
|
||||
}
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(cancelPrivate) object:nil];
|
||||
_cancellationRequested = YES;
|
||||
registrations = [self.registrations copy];
|
||||
}
|
||||
|
||||
[self notifyCancellation:registrations];
|
||||
}
|
||||
|
||||
- (void)notifyCancellation:(NSArray *)registrations {
|
||||
for (OSSCancellationTokenRegistration *registration in registrations) {
|
||||
[registration notifyDelegate];
|
||||
}
|
||||
}
|
||||
|
||||
- (OSSCancellationTokenRegistration *)registerCancellationObserverWithBlock:(OSSCancellationBlock)block {
|
||||
@synchronized(self.lock) {
|
||||
OSSCancellationTokenRegistration *registration = [OSSCancellationTokenRegistration registrationWithToken:self delegate:[block copy]];
|
||||
[self.registrations addObject:registration];
|
||||
|
||||
return registration;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)unregisterRegistration:(OSSCancellationTokenRegistration *)registration {
|
||||
@synchronized(self.lock) {
|
||||
[self throwIfDisposed];
|
||||
[self.registrations removeObject:registration];
|
||||
}
|
||||
}
|
||||
|
||||
// Delay on a non-public method to prevent interference with a user calling performSelector or
|
||||
// cancelPreviousPerformRequestsWithTarget on the public method
|
||||
- (void)cancelPrivate {
|
||||
[self cancel];
|
||||
}
|
||||
|
||||
- (void)cancelAfterDelay:(int)millis {
|
||||
[self throwIfDisposed];
|
||||
if (millis < -1) {
|
||||
[NSException raise:NSInvalidArgumentException format:@"Delay must be >= -1"];
|
||||
}
|
||||
|
||||
if (millis == 0) {
|
||||
[self cancel];
|
||||
return;
|
||||
}
|
||||
|
||||
@synchronized(self.lock) {
|
||||
[self throwIfDisposed];
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(cancelPrivate) object:nil];
|
||||
if (self.cancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (millis != -1) {
|
||||
double delay = (double)millis / 1000;
|
||||
[self performSelector:@selector(cancelPrivate) withObject:nil afterDelay:delay];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dispose {
|
||||
@synchronized(self.lock) {
|
||||
if (self.disposed) {
|
||||
return;
|
||||
}
|
||||
[self.registrations makeObjectsPerformSelector:@selector(dispose)];
|
||||
self.registrations = nil;
|
||||
self.disposed = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)throwIfDisposed {
|
||||
if (self.disposed) {
|
||||
[NSException raise:NSInternalInconsistencyException format:@"Object already disposed"];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
29
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSCancellationTokenRegistration.h
generated
Normal file
29
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSCancellationTokenRegistration.h
generated
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/*!
|
||||
Represents the registration of a cancellation observer with a cancellation token.
|
||||
Can be used to unregister the observer at a later time.
|
||||
*/
|
||||
@interface OSSCancellationTokenRegistration : NSObject
|
||||
|
||||
/*!
|
||||
Removes the cancellation observer registered with the token
|
||||
and releases all resources associated with this registration.
|
||||
*/
|
||||
- (void)dispose;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
79
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSCancellationTokenRegistration.m
generated
Normal file
79
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSCancellationTokenRegistration.m
generated
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#import "OSSCancellationTokenRegistration.h"
|
||||
|
||||
#import "OSSCancellationToken.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OSSCancellationTokenRegistration ()
|
||||
|
||||
@property (nonatomic, weak) OSSCancellationToken *token;
|
||||
@property (nullable, nonatomic, strong) OSSCancellationBlock cancellationObserverBlock;
|
||||
@property (nonatomic, strong) NSObject *lock;
|
||||
@property (nonatomic) BOOL disposed;
|
||||
|
||||
@end
|
||||
|
||||
@interface OSSCancellationToken (OSSCancellationTokenRegistration)
|
||||
|
||||
- (void)unregisterRegistration:(OSSCancellationTokenRegistration *)registration;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OSSCancellationTokenRegistration
|
||||
|
||||
+ (instancetype)registrationWithToken:(OSSCancellationToken *)token delegate:(OSSCancellationBlock)delegate {
|
||||
OSSCancellationTokenRegistration *registration = [OSSCancellationTokenRegistration new];
|
||||
registration.token = token;
|
||||
registration.cancellationObserverBlock = delegate;
|
||||
return registration;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (!self) return self;
|
||||
|
||||
_lock = [NSObject new];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dispose {
|
||||
@synchronized(self.lock) {
|
||||
if (self.disposed) {
|
||||
return;
|
||||
}
|
||||
self.disposed = YES;
|
||||
}
|
||||
|
||||
OSSCancellationToken *token = self.token;
|
||||
if (token != nil) {
|
||||
[token unregisterRegistration:self];
|
||||
self.token = nil;
|
||||
}
|
||||
self.cancellationObserverBlock = nil;
|
||||
}
|
||||
|
||||
- (void)notifyDelegate {
|
||||
@synchronized(self.lock) {
|
||||
[self throwIfDisposed];
|
||||
self.cancellationObserverBlock();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)throwIfDisposed {
|
||||
NSAssert(!self.disposed, @"Object already disposed");
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
60
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSCancellationTokenSource.h
generated
Normal file
60
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSCancellationTokenSource.h
generated
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class OSSCancellationToken;
|
||||
|
||||
/*!
|
||||
OSSCancellationTokenSource represents the producer side of a CancellationToken.
|
||||
Signals to a CancellationToken that it should be canceled.
|
||||
It is a cancellation token that also has methods
|
||||
for changing the state of a token by cancelling it.
|
||||
*/
|
||||
@interface OSSCancellationTokenSource : NSObject
|
||||
|
||||
/*!
|
||||
Creates a new cancellation token source.
|
||||
*/
|
||||
+ (instancetype)cancellationTokenSource;
|
||||
|
||||
/*!
|
||||
The cancellation token associated with this CancellationTokenSource.
|
||||
*/
|
||||
@property (nonatomic, strong, readonly) OSSCancellationToken *token;
|
||||
|
||||
/*!
|
||||
Whether cancellation has been requested for this token source.
|
||||
*/
|
||||
@property (nonatomic, assign, readonly, getter=isCancellationRequested) BOOL cancellationRequested;
|
||||
|
||||
/*!
|
||||
Cancels the token if it has not already been cancelled.
|
||||
*/
|
||||
- (void)cancel;
|
||||
|
||||
/*!
|
||||
Schedules a cancel operation on this CancellationTokenSource after the specified number of milliseconds.
|
||||
@param millis The number of milliseconds to wait before completing the returned task.
|
||||
If delay is `0` the cancel is executed immediately. If delay is `-1` any scheduled cancellation is stopped.
|
||||
*/
|
||||
- (void)cancelAfterDelay:(int)millis;
|
||||
|
||||
/*!
|
||||
Releases all resources associated with this token source,
|
||||
including disposing of all registrations.
|
||||
*/
|
||||
- (void)dispose;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
64
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSCancellationTokenSource.m
generated
Normal file
64
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSCancellationTokenSource.m
generated
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#import "OSSCancellationTokenSource.h"
|
||||
|
||||
#import "OSSCancellationToken.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OSSCancellationToken (OSSCancellationTokenSource)
|
||||
|
||||
- (void)cancel;
|
||||
- (void)cancelAfterDelay:(int)millis;
|
||||
|
||||
- (void)dispose;
|
||||
- (void)throwIfDisposed;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OSSCancellationTokenSource
|
||||
|
||||
#pragma mark - Initializer
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (!self) return self;
|
||||
|
||||
_token = [OSSCancellationToken new];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)cancellationTokenSource {
|
||||
return [OSSCancellationTokenSource new];
|
||||
}
|
||||
|
||||
#pragma mark - Custom Setters/Getters
|
||||
|
||||
- (BOOL)isCancellationRequested {
|
||||
return _token.isCancellationRequested;
|
||||
}
|
||||
|
||||
- (void)cancel {
|
||||
[_token cancel];
|
||||
}
|
||||
|
||||
- (void)cancelAfterDelay:(int)millis {
|
||||
[_token cancelAfterDelay:millis];
|
||||
}
|
||||
|
||||
- (void)dispose {
|
||||
[_token dispose];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
62
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSExecutor.h
generated
Normal file
62
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSExecutor.h
generated
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/*!
|
||||
An object that can run a given block.
|
||||
*/
|
||||
@interface OSSExecutor : NSObject
|
||||
|
||||
/*!
|
||||
Returns a default executor, which runs continuations immediately until the call stack gets too
|
||||
deep, then dispatches to a new GCD queue.
|
||||
*/
|
||||
+ (instancetype)defaultExecutor;
|
||||
|
||||
/*!
|
||||
Returns an executor that runs continuations on the thread where the previous task was completed.
|
||||
*/
|
||||
+ (instancetype)immediateExecutor;
|
||||
|
||||
/*!
|
||||
Returns an executor that runs continuations on the main thread.
|
||||
*/
|
||||
+ (instancetype)mainThreadExecutor;
|
||||
|
||||
/*!
|
||||
Returns a new executor that uses the given block to execute continuations.
|
||||
@param block The block to use.
|
||||
*/
|
||||
+ (instancetype)executorWithBlock:(void(^)(void(^block)(void)))block;
|
||||
|
||||
/*!
|
||||
Returns a new executor that runs continuations on the given queue.
|
||||
@param queue The instance of `dispatch_queue_t` to dispatch all continuations onto.
|
||||
*/
|
||||
+ (instancetype)executorWithDispatchQueue:(dispatch_queue_t)queue;
|
||||
|
||||
/*!
|
||||
Returns a new executor that runs continuations on the given queue.
|
||||
@param queue The instance of `NSOperationQueue` to run all continuations on.
|
||||
*/
|
||||
+ (instancetype)executorWithOperationQueue:(NSOperationQueue *)queue;
|
||||
|
||||
/*!
|
||||
Runs the given block using this executor's particular strategy.
|
||||
@param block The block to execute.
|
||||
*/
|
||||
- (void)execute:(void(^)(void))block;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
136
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSExecutor.m
generated
Normal file
136
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSExecutor.m
generated
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#import "OSSExecutor.h"
|
||||
|
||||
#import <pthread.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/*!
|
||||
Get the remaining stack-size of the current thread.
|
||||
|
||||
@param totalSize The total stack size of the current thread.
|
||||
|
||||
@return The remaining size, in bytes, available to the current thread.
|
||||
|
||||
@note This function cannot be inlined, as otherwise the internal implementation could fail to report the proper
|
||||
remaining stack space.
|
||||
*/
|
||||
__attribute__((noinline)) static size_t remaining_stack_size(size_t *restrict totalSize) {
|
||||
pthread_t currentThread = pthread_self();
|
||||
|
||||
// NOTE: We must store stack pointers as uint8_t so that the pointer math is well-defined
|
||||
uint8_t *endStack = pthread_get_stackaddr_np(currentThread);
|
||||
*totalSize = pthread_get_stacksize_np(currentThread);
|
||||
|
||||
// NOTE: If the function is inlined, this value could be incorrect
|
||||
uint8_t *frameAddr = __builtin_frame_address(0);
|
||||
|
||||
return (*totalSize) - (endStack - frameAddr);
|
||||
}
|
||||
|
||||
@interface OSSExecutor ()
|
||||
|
||||
@property (nonatomic, copy) void(^block)(void(^block)(void));
|
||||
|
||||
@end
|
||||
|
||||
@implementation OSSExecutor
|
||||
|
||||
#pragma mark - Executor methods
|
||||
|
||||
+ (instancetype)defaultExecutor {
|
||||
static OSSExecutor *defaultExecutor = NULL;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
defaultExecutor = [self executorWithBlock:^void(void(^block)(void)) {
|
||||
// We prefer to run everything possible immediately, so that there is callstack information
|
||||
// when debugging. However, we don't want the stack to get too deep, so if the remaining stack space
|
||||
// is less than 10% of the total space, we dispatch to another GCD queue.
|
||||
size_t totalStackSize = 0;
|
||||
size_t remainingStackSize = remaining_stack_size(&totalStackSize);
|
||||
|
||||
if (remainingStackSize < (totalStackSize / 10)) {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block);
|
||||
} else {
|
||||
@autoreleasepool {
|
||||
block();
|
||||
}
|
||||
}
|
||||
}];
|
||||
});
|
||||
return defaultExecutor;
|
||||
}
|
||||
|
||||
+ (instancetype)immediateExecutor {
|
||||
static OSSExecutor *immediateExecutor = NULL;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
immediateExecutor = [self executorWithBlock:^void(void(^block)(void)) {
|
||||
block();
|
||||
}];
|
||||
});
|
||||
return immediateExecutor;
|
||||
}
|
||||
|
||||
+ (instancetype)mainThreadExecutor {
|
||||
static OSSExecutor *mainThreadExecutor = NULL;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
mainThreadExecutor = [self executorWithBlock:^void(void(^block)(void)) {
|
||||
if (![NSThread isMainThread]) {
|
||||
dispatch_async(dispatch_get_main_queue(), block);
|
||||
} else {
|
||||
@autoreleasepool {
|
||||
block();
|
||||
}
|
||||
}
|
||||
}];
|
||||
});
|
||||
return mainThreadExecutor;
|
||||
}
|
||||
|
||||
+ (instancetype)executorWithBlock:(void(^)(void(^block)(void)))block {
|
||||
return [[self alloc] initWithBlock:block];
|
||||
}
|
||||
|
||||
+ (instancetype)executorWithDispatchQueue:(dispatch_queue_t)queue {
|
||||
return [self executorWithBlock:^void(void(^block)(void)) {
|
||||
dispatch_async(queue, block);
|
||||
}];
|
||||
}
|
||||
|
||||
+ (instancetype)executorWithOperationQueue:(NSOperationQueue *)queue {
|
||||
return [self executorWithBlock:^void(void(^block)(void)) {
|
||||
[queue addOperation:[NSBlockOperation blockOperationWithBlock:block]];
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Initializer
|
||||
|
||||
- (instancetype)initWithBlock:(void(^)(void(^block)(void)))block {
|
||||
self = [super init];
|
||||
if (!self) return self;
|
||||
|
||||
_block = block;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Execution
|
||||
|
||||
- (void)execute:(void(^)(void))block {
|
||||
self.block(block);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
295
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSTask.h
generated
Normal file
295
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSTask.h
generated
Normal file
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "OSSCancellationToken.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/*!
|
||||
Error domain used if there was multiple errors on <OSSTask taskForCompletionOfAllTasks:>.
|
||||
*/
|
||||
extern NSString *const OSSTaskErrorDomain;
|
||||
|
||||
/*!
|
||||
An error code used for <OSSTask taskForCompletionOfAllTasks:>, if there were multiple errors.
|
||||
*/
|
||||
extern NSInteger const kOSSMultipleErrorsError;
|
||||
|
||||
/*!
|
||||
An exception that is thrown if there was multiple exceptions on <OSSTask taskForCompletionOfAllTasks:>.
|
||||
*/
|
||||
extern NSString *const OSSTaskMultipleExceptionsException;
|
||||
|
||||
/*!
|
||||
An error userInfo key used if there were multiple errors on <OSSTask taskForCompletionOfAllTasks:>.
|
||||
Value type is `NSArray<NSError *> *`.
|
||||
*/
|
||||
extern NSString *const OSSTaskMultipleErrorsUserInfoKey;
|
||||
|
||||
/*!
|
||||
An error userInfo key used if there were multiple exceptions on <OSSTask taskForCompletionOfAllTasks:>.
|
||||
Value type is `NSArray<NSException *> *`.
|
||||
*/
|
||||
extern NSString *const OSSTaskMultipleExceptionsUserInfoKey;
|
||||
|
||||
@class OSSExecutor;
|
||||
@class OSSTask;
|
||||
|
||||
/*!
|
||||
The consumer view of a Task. A OSSTask has methods to
|
||||
inspect the state of the task, and to add continuations to
|
||||
be run once the task is complete.
|
||||
*/
|
||||
@interface OSSTask<__covariant ResultType> : NSObject
|
||||
|
||||
/*!
|
||||
A block that can act as a continuation for a task.
|
||||
*/
|
||||
typedef __nullable id(^OSSContinuationBlock)(OSSTask<ResultType> *task);
|
||||
|
||||
/*!
|
||||
Creates a task that is already completed with the given result.
|
||||
@param result The result for the task.
|
||||
*/
|
||||
+ (instancetype)taskWithResult:(_Nullable ResultType)result;
|
||||
|
||||
/*!
|
||||
Creates a task that is already completed with the given error.
|
||||
@param error The error for the task.
|
||||
*/
|
||||
+ (instancetype)taskWithError:(NSError *)error;
|
||||
|
||||
/*!
|
||||
Creates a task that is already completed with the given exception.
|
||||
@param exception The exception for the task.
|
||||
*/
|
||||
+ (instancetype)taskWithException:(NSException *)exception;
|
||||
|
||||
/*!
|
||||
Creates a task that is already cancelled.
|
||||
*/
|
||||
+ (instancetype)cancelledTask;
|
||||
|
||||
/*!
|
||||
Returns a task that will be completed (with result == nil) once
|
||||
all of the input tasks have completed.
|
||||
@param tasks An `NSArray` of the tasks to use as an input.
|
||||
*/
|
||||
+ (instancetype)taskForCompletionOfAllTasks:(nullable NSArray<OSSTask *> *)tasks;
|
||||
|
||||
/*!
|
||||
Returns a task that will be completed once all of the input tasks have completed.
|
||||
If all tasks complete successfully without being faulted or cancelled the result will be
|
||||
an `NSArray` of all task results in the order they were provided.
|
||||
@param tasks An `NSArray` of the tasks to use as an input.
|
||||
*/
|
||||
+ (instancetype)taskForCompletionOfAllTasksWithResults:(nullable NSArray<OSSTask *> *)tasks;
|
||||
|
||||
/*!
|
||||
Returns a task that will be completed once there is at least one successful task.
|
||||
The first task to successuly complete will set the result, all other tasks results are
|
||||
ignored.
|
||||
@param tasks An `NSArray` of the tasks to use as an input.
|
||||
*/
|
||||
+ (instancetype)taskForCompletionOfAnyTask:(nullable NSArray<OSSTask *> *)tasks;
|
||||
|
||||
/*!
|
||||
Returns a task that will be completed a certain amount of time in the future.
|
||||
@param millis The approximate number of milliseconds to wait before the
|
||||
task will be finished (with result == nil).
|
||||
*/
|
||||
+ (instancetype)taskWithDelay:(int)millis;
|
||||
|
||||
/*!
|
||||
Returns a task that will be completed a certain amount of time in the future.
|
||||
@param millis The approximate number of milliseconds to wait before the
|
||||
task will be finished (with result == nil).
|
||||
@param token The cancellation token (optional).
|
||||
*/
|
||||
+ (instancetype)taskWithDelay:(int)millis cancellationToken:(nullable OSSCancellationToken *)token;
|
||||
|
||||
/*!
|
||||
Returns a task that will be completed after the given block completes with
|
||||
the specified executor.
|
||||
@param executor A OSSExecutor responsible for determining how the
|
||||
continuation block will be run.
|
||||
@param block The block to immediately schedule to run with the given executor.
|
||||
@returns A task that will be completed after block has run.
|
||||
If block returns a OSSTask, then the task returned from
|
||||
this method will not be completed until that task is completed.
|
||||
*/
|
||||
+ (instancetype)taskFromExecutor:(OSSExecutor *)executor withBlock:(nullable id (^)(void))block;
|
||||
|
||||
// Properties that will be set on the task once it is completed.
|
||||
|
||||
/*!
|
||||
The result of a successful task.
|
||||
*/
|
||||
@property (nullable, nonatomic, strong, readonly) ResultType result;
|
||||
|
||||
/*!
|
||||
The error of a failed task.
|
||||
*/
|
||||
@property (nullable, nonatomic, strong, readonly) NSError *error;
|
||||
|
||||
/*!
|
||||
The exception of a failed task.
|
||||
*/
|
||||
@property (nullable, nonatomic, strong, readonly) NSException *exception;
|
||||
|
||||
/*!
|
||||
Whether this task has been cancelled.
|
||||
*/
|
||||
@property (nonatomic, assign, readonly, getter=isCancelled) BOOL cancelled;
|
||||
|
||||
/*!
|
||||
Whether this task has completed due to an error or exception.
|
||||
*/
|
||||
@property (nonatomic, assign, readonly, getter=isFaulted) BOOL faulted;
|
||||
|
||||
/*!
|
||||
Whether this task has completed.
|
||||
*/
|
||||
@property (nonatomic, assign, readonly, getter=isCompleted) BOOL completed;
|
||||
|
||||
/*!
|
||||
Enqueues the given block to be run once this task is complete.
|
||||
This method uses a default execution strategy. The block will be
|
||||
run on the thread where the previous task completes, unless the
|
||||
the stack depth is too deep, in which case it will be run on a
|
||||
dispatch queue with default priority.
|
||||
@param block The block to be run once this task is complete.
|
||||
@returns A task that will be completed after block has run.
|
||||
If block returns a OSSTask, then the task returned from
|
||||
this method will not be completed until that task is completed.
|
||||
*/
|
||||
- (OSSTask *)continueWithBlock:(OSSContinuationBlock)block;
|
||||
|
||||
/*!
|
||||
Enqueues the given block to be run once this task is complete.
|
||||
This method uses a default execution strategy. The block will be
|
||||
run on the thread where the previous task completes, unless the
|
||||
the stack depth is too deep, in which case it will be run on a
|
||||
dispatch queue with default priority.
|
||||
@param block The block to be run once this task is complete.
|
||||
@param cancellationToken The cancellation token (optional).
|
||||
@returns A task that will be completed after block has run.
|
||||
If block returns a OSSTask, then the task returned from
|
||||
this method will not be completed until that task is completed.
|
||||
*/
|
||||
- (OSSTask *)continueWithBlock:(OSSContinuationBlock)block cancellationToken:(nullable OSSCancellationToken *)cancellationToken;
|
||||
|
||||
/*!
|
||||
Enqueues the given block to be run once this task is complete.
|
||||
@param executor A OSSExecutor responsible for determining how the
|
||||
continuation block will be run.
|
||||
@param block The block to be run once this task is complete.
|
||||
@returns A task that will be completed after block has run.
|
||||
If block returns a OSSTask, then the task returned from
|
||||
this method will not be completed until that task is completed.
|
||||
*/
|
||||
- (OSSTask *)continueWithExecutor:(OSSExecutor *)executor withBlock:(OSSContinuationBlock)block;
|
||||
/*!
|
||||
Enqueues the given block to be run once this task is complete.
|
||||
@param executor A OSSExecutor responsible for determining how the
|
||||
continuation block will be run.
|
||||
@param block The block to be run once this task is complete.
|
||||
@param cancellationToken The cancellation token (optional).
|
||||
@returns A task that will be completed after block has run.
|
||||
If block returns a OSSTask, then the task returned from
|
||||
his method will not be completed until that task is completed.
|
||||
*/
|
||||
- (OSSTask *)continueWithExecutor:(OSSExecutor *)executor
|
||||
block:(OSSContinuationBlock)block
|
||||
cancellationToken:(nullable OSSCancellationToken *)cancellationToken;
|
||||
|
||||
/*!
|
||||
Identical to continueWithBlock:, except that the block is only run
|
||||
if this task did not produce a cancellation, error, or exception.
|
||||
If it did, then the failure will be propagated to the returned
|
||||
task.
|
||||
@param block The block to be run once this task is complete.
|
||||
@returns A task that will be completed after block has run.
|
||||
If block returns a OSSTask, then the task returned from
|
||||
this method will not be completed until that task is completed.
|
||||
*/
|
||||
- (OSSTask *)continueWithSuccessBlock:(OSSContinuationBlock)block;
|
||||
|
||||
/*!
|
||||
Identical to continueWithBlock:, except that the block is only run
|
||||
if this task did not produce a cancellation, error, or exception.
|
||||
If it did, then the failure will be propagated to the returned
|
||||
task.
|
||||
@param block The block to be run once this task is complete.
|
||||
@param cancellationToken The cancellation token (optional).
|
||||
@returns A task that will be completed after block has run.
|
||||
If block returns a OSSTask, then the task returned from
|
||||
this method will not be completed until that task is completed.
|
||||
*/
|
||||
- (OSSTask *)continueWithSuccessBlock:(OSSContinuationBlock)block cancellationToken:(nullable OSSCancellationToken *)cancellationToken;
|
||||
|
||||
/*!
|
||||
Identical to continueWithExecutor:withBlock:, except that the block
|
||||
is only run if this task did not produce a cancellation, error, or
|
||||
exception. If it did, then the failure will be propagated to the
|
||||
returned task.
|
||||
@param executor A OSSExecutor responsible for determining how the
|
||||
continuation block will be run.
|
||||
@param block The block to be run once this task is complete.
|
||||
@returns A task that will be completed after block has run.
|
||||
If block returns a OSSTask, then the task returned from
|
||||
this method will not be completed until that task is completed.
|
||||
*/
|
||||
- (OSSTask *)continueWithExecutor:(OSSExecutor *)executor withSuccessBlock:(OSSContinuationBlock)block;
|
||||
|
||||
/*!
|
||||
Identical to continueWithExecutor:withBlock:, except that the block
|
||||
is only run if this task did not produce a cancellation, error, or
|
||||
exception. If it did, then the failure will be propagated to the
|
||||
returned task.
|
||||
@param executor A OSSExecutor responsible for determining how the
|
||||
continuation block will be run.
|
||||
@param block The block to be run once this task is complete.
|
||||
@param cancellationToken The cancellation token (optional).
|
||||
@returns A task that will be completed after block has run.
|
||||
If block returns a OSSTask, then the task returned from
|
||||
this method will not be completed until that task is completed.
|
||||
*/
|
||||
- (OSSTask *)continueWithExecutor:(OSSExecutor *)executor
|
||||
successBlock:(OSSContinuationBlock)block
|
||||
cancellationToken:(nullable OSSCancellationToken *)cancellationToken;
|
||||
|
||||
/*!
|
||||
Waits until this operation is completed.
|
||||
This method is inefficient and consumes a thread resource while
|
||||
it's running. It should be avoided. This method logs a warning
|
||||
message if it is used on the main thread.
|
||||
*/
|
||||
- (void)waitUntilFinished;
|
||||
|
||||
@end
|
||||
|
||||
@class OSSResult;
|
||||
|
||||
@interface OSSTask(OSS)
|
||||
|
||||
typedef void(^OSSCompleteBlock)(BOOL isSuccess, NSError * _Nullable error, OSSResult * _Nullable result);
|
||||
|
||||
- (BOOL)isSuccessful;
|
||||
|
||||
- (NSError *)toError;
|
||||
|
||||
- (OSSTask *)completed:(OSSCompleteBlock)block;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
584
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSTask.m
generated
Normal file
584
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSTask.m
generated
Normal file
@@ -0,0 +1,584 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#import "OSSTask.h"
|
||||
#import "OSSLog.h"
|
||||
#import "OSSConstants.h"
|
||||
#import "OSSDefine.h"
|
||||
|
||||
#import <libkern/OSAtomic.h>
|
||||
|
||||
#import "OSSBolts.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
__attribute__ ((noinline)) void ossWarnBlockingOperationOnMainThread() {
|
||||
NSLog(@"Warning: A long-running operation is being executed on the main thread. \n"
|
||||
" Break on warnBlockingOperationOnMainThread() to debug.");
|
||||
}
|
||||
|
||||
NSString *const OSSTaskErrorDomain = @"bolts";
|
||||
NSInteger const kOSSMultipleErrorsError = 80175001;
|
||||
NSString *const OSSTaskMultipleExceptionsException = @"OSSMultipleExceptionsException";
|
||||
|
||||
NSString *const OSSTaskMultipleErrorsUserInfoKey = @"errors";
|
||||
NSString *const OSSTaskMultipleExceptionsUserInfoKey = @"exceptions";
|
||||
|
||||
@interface OSSTask () {
|
||||
id _result;
|
||||
NSError *_error;
|
||||
NSException *_exception;
|
||||
}
|
||||
|
||||
@property (nonatomic, assign, readwrite, getter=isCancelled) BOOL cancelled;
|
||||
@property (nonatomic, assign, readwrite, getter=isFaulted) BOOL faulted;
|
||||
@property (nonatomic, assign, readwrite, getter=isCompleted) BOOL completed;
|
||||
|
||||
@property (nonatomic, strong) NSObject *lock;
|
||||
@property (nonatomic, strong) NSCondition *condition;
|
||||
@property (nonatomic, strong) NSMutableArray *callbacks;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OSSTask
|
||||
|
||||
#pragma mark - Initializer
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (!self) return self;
|
||||
|
||||
_lock = [[NSObject alloc] init];
|
||||
_condition = [[NSCondition alloc] init];
|
||||
_callbacks = [NSMutableArray array];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithResult:(_Nullable id)result {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self trySetResult:result];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithError:(NSError *)error {
|
||||
self = [super init];
|
||||
if (!self) return self;
|
||||
|
||||
[self trySetError:error];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithException:(NSException *)exception {
|
||||
self = [super init];
|
||||
if (!self) return self;
|
||||
|
||||
[self trySetException:exception];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initCancelled {
|
||||
self = [super init];
|
||||
if (!self) return self;
|
||||
|
||||
[self trySetCancelled];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Task Class methods
|
||||
|
||||
+ (instancetype)taskWithResult:(_Nullable id)result {
|
||||
return [[self alloc] initWithResult:result];
|
||||
}
|
||||
|
||||
+ (instancetype)taskWithError:(NSError *)error {
|
||||
return [[self alloc] initWithError:error];
|
||||
}
|
||||
|
||||
+ (instancetype)taskWithException:(NSException *)exception {
|
||||
return [[self alloc] initWithException:exception];
|
||||
}
|
||||
|
||||
+ (instancetype)cancelledTask {
|
||||
return [[self alloc] initCancelled];
|
||||
}
|
||||
|
||||
+ (instancetype)taskForCompletionOfAllTasks:(nullable NSArray<OSSTask *> *)tasks {
|
||||
__block int32_t total = (int32_t)tasks.count;
|
||||
if (total == 0) {
|
||||
return [self taskWithResult:nil];
|
||||
}
|
||||
|
||||
__block int32_t cancelled = 0;
|
||||
NSObject *lock = [[NSObject alloc] init];
|
||||
NSMutableArray *errors = [NSMutableArray array];
|
||||
NSMutableArray *exceptions = [NSMutableArray array];
|
||||
|
||||
OSSTaskCompletionSource *tcs = [OSSTaskCompletionSource taskCompletionSource];
|
||||
for (OSSTask *task in tasks) {
|
||||
[task continueWithBlock:^id(OSSTask *task) {
|
||||
if (task.exception) {
|
||||
@synchronized (lock) {
|
||||
[exceptions addObject:task.exception];
|
||||
}
|
||||
} else if (task.error) {
|
||||
@synchronized (lock) {
|
||||
[errors addObject:task.error];
|
||||
}
|
||||
} else if (task.cancelled) {
|
||||
OSAtomicIncrement32Barrier(&cancelled);
|
||||
}
|
||||
|
||||
if (OSAtomicDecrement32Barrier(&total) == 0) {
|
||||
if (exceptions.count > 0) {
|
||||
if (exceptions.count == 1) {
|
||||
tcs.exception = [exceptions firstObject];
|
||||
} else {
|
||||
NSException *exception =
|
||||
[NSException exceptionWithName:OSSTaskMultipleExceptionsException
|
||||
reason:@"There were multiple exceptions."
|
||||
userInfo:@{ OSSTaskMultipleExceptionsUserInfoKey: exceptions }];
|
||||
tcs.exception = exception;
|
||||
}
|
||||
} else if (errors.count > 0) {
|
||||
if (errors.count == 1) {
|
||||
tcs.error = [errors firstObject];
|
||||
} else {
|
||||
NSError *error = [NSError errorWithDomain:OSSTaskErrorDomain
|
||||
code:kOSSMultipleErrorsError
|
||||
userInfo:@{ OSSTaskMultipleErrorsUserInfoKey: errors }];
|
||||
tcs.error = error;
|
||||
}
|
||||
} else if (cancelled > 0) {
|
||||
[tcs cancel];
|
||||
} else {
|
||||
tcs.result = nil;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}];
|
||||
}
|
||||
return tcs.task;
|
||||
}
|
||||
|
||||
+ (instancetype)taskForCompletionOfAllTasksWithResults:(nullable NSArray<OSSTask *> *)tasks {
|
||||
return [[self taskForCompletionOfAllTasks:tasks] continueWithSuccessBlock:^id(OSSTask *task) {
|
||||
return [tasks valueForKey:@"result"];
|
||||
}];
|
||||
}
|
||||
|
||||
+ (instancetype)taskForCompletionOfAnyTask:(nullable NSArray<OSSTask *> *)tasks
|
||||
{
|
||||
__block int32_t total = (int32_t)tasks.count;
|
||||
if (total == 0) {
|
||||
return [self taskWithResult:nil];
|
||||
}
|
||||
|
||||
__block int completed = 0;
|
||||
__block int32_t cancelled = 0;
|
||||
|
||||
NSObject *lock = [NSObject new];
|
||||
NSMutableArray<NSError *> *errors = [NSMutableArray new];
|
||||
NSMutableArray<NSException *> *exceptions = [NSMutableArray new];
|
||||
|
||||
OSSTaskCompletionSource *source = [OSSTaskCompletionSource taskCompletionSource];
|
||||
for (OSSTask *task in tasks) {
|
||||
[task continueWithBlock:^id(OSSTask *task) {
|
||||
if (task.exception != nil) {
|
||||
@synchronized(lock) {
|
||||
[exceptions addObject:task.exception];
|
||||
}
|
||||
} else if (task.error != nil) {
|
||||
@synchronized(lock) {
|
||||
[errors addObject:task.error];
|
||||
}
|
||||
} else if (task.cancelled) {
|
||||
OSAtomicIncrement32Barrier(&cancelled);
|
||||
} else {
|
||||
if(OSAtomicCompareAndSwap32Barrier(0, 1, &completed)) {
|
||||
[source setResult:task.result];
|
||||
}
|
||||
}
|
||||
|
||||
if (OSAtomicDecrement32Barrier(&total) == 0 &&
|
||||
OSAtomicCompareAndSwap32Barrier(0, 1, &completed)) {
|
||||
if (cancelled > 0) {
|
||||
[source cancel];
|
||||
} else if (exceptions.count > 0) {
|
||||
if (exceptions.count == 1) {
|
||||
source.exception = exceptions.firstObject;
|
||||
} else {
|
||||
NSException *exception =
|
||||
[NSException exceptionWithName:OSSTaskMultipleExceptionsException
|
||||
reason:@"There were multiple exceptions."
|
||||
userInfo:@{ @"exceptions": exceptions }];
|
||||
source.exception = exception;
|
||||
}
|
||||
} else if (errors.count > 0) {
|
||||
if (errors.count == 1) {
|
||||
source.error = errors.firstObject;
|
||||
} else {
|
||||
NSError *error = [NSError errorWithDomain:OSSTaskErrorDomain
|
||||
code:kOSSMultipleErrorsError
|
||||
userInfo:@{ @"errors": errors }];
|
||||
source.error = error;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Abort execution of per tasks continuations
|
||||
return nil;
|
||||
}];
|
||||
}
|
||||
return source.task;
|
||||
}
|
||||
|
||||
|
||||
+ (instancetype)taskWithDelay:(int)millis {
|
||||
OSSTaskCompletionSource *tcs = [OSSTaskCompletionSource taskCompletionSource];
|
||||
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, millis * NSEC_PER_MSEC);
|
||||
dispatch_after(popTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
|
||||
tcs.result = nil;
|
||||
});
|
||||
return tcs.task;
|
||||
}
|
||||
|
||||
+ (instancetype)taskWithDelay:(int)millis cancellationToken:(nullable OSSCancellationToken *)token {
|
||||
if (token.cancellationRequested) {
|
||||
return [OSSTask cancelledTask];
|
||||
}
|
||||
|
||||
OSSTaskCompletionSource *tcs = [OSSTaskCompletionSource taskCompletionSource];
|
||||
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, millis * NSEC_PER_MSEC);
|
||||
dispatch_after(popTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
|
||||
if (token.cancellationRequested) {
|
||||
[tcs cancel];
|
||||
return;
|
||||
}
|
||||
tcs.result = nil;
|
||||
});
|
||||
return tcs.task;
|
||||
}
|
||||
|
||||
+ (instancetype)taskFromExecutor:(OSSExecutor *)executor withBlock:(nullable id (^)(void))block {
|
||||
return [[self taskWithResult:nil] continueWithExecutor:executor withBlock:^id(OSSTask *task) {
|
||||
return block();
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Custom Setters/Getters
|
||||
|
||||
- (nullable id)result {
|
||||
@synchronized(self.lock) {
|
||||
return _result;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)trySetResult:(nullable id)result {
|
||||
@synchronized(self.lock) {
|
||||
if (self.completed) {
|
||||
return NO;
|
||||
}
|
||||
self.completed = YES;
|
||||
_result = result;
|
||||
[self runContinuations];
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable NSError *)error {
|
||||
@synchronized(self.lock) {
|
||||
return _error;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)trySetError:(NSError *)error {
|
||||
@synchronized(self.lock) {
|
||||
if (self.completed) {
|
||||
return NO;
|
||||
}
|
||||
self.completed = YES;
|
||||
self.faulted = YES;
|
||||
_error = error;
|
||||
[self runContinuations];
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable NSException *)exception {
|
||||
@synchronized(self.lock) {
|
||||
return _exception;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)trySetException:(NSException *)exception {
|
||||
@synchronized(self.lock) {
|
||||
if (self.completed) {
|
||||
return NO;
|
||||
}
|
||||
self.completed = YES;
|
||||
self.faulted = YES;
|
||||
_exception = exception;
|
||||
[self runContinuations];
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isCancelled {
|
||||
@synchronized(self.lock) {
|
||||
return _cancelled;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isFaulted {
|
||||
@synchronized(self.lock) {
|
||||
return _faulted;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)trySetCancelled {
|
||||
@synchronized(self.lock) {
|
||||
if (self.completed) {
|
||||
return NO;
|
||||
}
|
||||
self.completed = YES;
|
||||
self.cancelled = YES;
|
||||
[self runContinuations];
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isCompleted {
|
||||
@synchronized(self.lock) {
|
||||
return _completed;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)runContinuations {
|
||||
@synchronized(self.lock) {
|
||||
[self.condition lock];
|
||||
[self.condition broadcast];
|
||||
[self.condition unlock];
|
||||
for (void (^callback)(void) in self.callbacks) {
|
||||
callback();
|
||||
}
|
||||
[self.callbacks removeAllObjects];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Chaining methods
|
||||
|
||||
- (OSSTask *)continueWithExecutor:(OSSExecutor *)executor withBlock:(OSSContinuationBlock)block {
|
||||
return [self continueWithExecutor:executor block:block cancellationToken:nil];
|
||||
}
|
||||
|
||||
- (OSSTask *)continueWithExecutor:(OSSExecutor *)executor
|
||||
block:(OSSContinuationBlock)block
|
||||
cancellationToken:(nullable OSSCancellationToken *)cancellationToken {
|
||||
OSSTaskCompletionSource *tcs = [OSSTaskCompletionSource taskCompletionSource];
|
||||
|
||||
// Capture all of the state that needs to used when the continuation is complete.
|
||||
dispatch_block_t executionBlock = ^{
|
||||
if (cancellationToken.cancellationRequested) {
|
||||
[tcs cancel];
|
||||
return;
|
||||
}
|
||||
|
||||
id result = nil;
|
||||
@try {
|
||||
result = block(self);
|
||||
} @catch (NSException *exception) {
|
||||
NSError *error = [NSError errorWithDomain:OSSClientErrorDomain
|
||||
code:OSSClientErrorCodeExcpetionCatched
|
||||
userInfo:@{OSSErrorMessageTOKEN: [NSString stringWithFormat:@"Catch exception - %@", exception]}];
|
||||
tcs.error = error;
|
||||
OSSLogError(@"exception name: %@",[exception name]);
|
||||
OSSLogError(@"exception reason: %@",[exception reason]);
|
||||
return;
|
||||
}
|
||||
|
||||
if ([result isKindOfClass:[OSSTask class]]) {
|
||||
|
||||
id (^setupWithTask) (OSSTask *) = ^id(OSSTask *task) {
|
||||
if (cancellationToken.cancellationRequested || task.cancelled) {
|
||||
[tcs cancel];
|
||||
} else if (task.exception) {
|
||||
NSError *error = [NSError errorWithDomain:OSSClientErrorDomain
|
||||
code:OSSClientErrorCodeExcpetionCatched
|
||||
userInfo:@{OSSErrorMessageTOKEN: [NSString stringWithFormat:@"Catch exception - %@", task.exception]}];
|
||||
tcs.error = error;
|
||||
} else if (task.error) {
|
||||
tcs.error = task.error;
|
||||
} else {
|
||||
tcs.result = task.result;
|
||||
}
|
||||
return nil;
|
||||
};
|
||||
|
||||
OSSTask *resultTask = (OSSTask *)result;
|
||||
|
||||
if (resultTask.completed) {
|
||||
setupWithTask(resultTask);
|
||||
} else {
|
||||
[resultTask continueWithBlock:setupWithTask];
|
||||
}
|
||||
|
||||
} else {
|
||||
tcs.result = result;
|
||||
}
|
||||
};
|
||||
|
||||
BOOL completed;
|
||||
@synchronized(self.lock) {
|
||||
completed = self.completed;
|
||||
if (!completed) {
|
||||
[self.callbacks addObject:[^{
|
||||
[executor execute:executionBlock];
|
||||
} copy]];
|
||||
}
|
||||
}
|
||||
if (completed) {
|
||||
[executor execute:executionBlock];
|
||||
}
|
||||
|
||||
return tcs.task;
|
||||
}
|
||||
|
||||
- (OSSTask *)continueWithBlock:(OSSContinuationBlock)block {
|
||||
return [self continueWithExecutor:[OSSExecutor defaultExecutor] block:block cancellationToken:nil];
|
||||
}
|
||||
|
||||
- (OSSTask *)continueWithBlock:(OSSContinuationBlock)block cancellationToken:(nullable OSSCancellationToken *)cancellationToken {
|
||||
return [self continueWithExecutor:[OSSExecutor defaultExecutor] block:block cancellationToken:cancellationToken];
|
||||
}
|
||||
|
||||
- (OSSTask *)continueWithExecutor:(OSSExecutor *)executor
|
||||
withSuccessBlock:(OSSContinuationBlock)block {
|
||||
return [self continueWithExecutor:executor successBlock:block cancellationToken:nil];
|
||||
}
|
||||
|
||||
- (OSSTask *)continueWithExecutor:(OSSExecutor *)executor
|
||||
successBlock:(OSSContinuationBlock)block
|
||||
cancellationToken:(nullable OSSCancellationToken *)cancellationToken {
|
||||
if (cancellationToken.cancellationRequested) {
|
||||
return [OSSTask cancelledTask];
|
||||
}
|
||||
|
||||
return [self continueWithExecutor:executor block:^id(OSSTask *task) {
|
||||
if (task.faulted || task.cancelled) {
|
||||
return task;
|
||||
} else {
|
||||
return block(task);
|
||||
}
|
||||
} cancellationToken:cancellationToken];
|
||||
}
|
||||
|
||||
- (OSSTask *)continueWithSuccessBlock:(OSSContinuationBlock)block {
|
||||
return [self continueWithExecutor:[OSSExecutor defaultExecutor] successBlock:block cancellationToken:nil];
|
||||
}
|
||||
|
||||
- (OSSTask *)continueWithSuccessBlock:(OSSContinuationBlock)block cancellationToken:(nullable OSSCancellationToken *)cancellationToken {
|
||||
return [self continueWithExecutor:[OSSExecutor defaultExecutor] successBlock:block cancellationToken:cancellationToken];
|
||||
}
|
||||
|
||||
#pragma mark - Syncing Task (Avoid it)
|
||||
|
||||
- (void)warnOperationOnMainThread {
|
||||
ossWarnBlockingOperationOnMainThread();
|
||||
}
|
||||
|
||||
- (void)waitUntilFinished {
|
||||
if ([NSThread isMainThread]) {
|
||||
[self warnOperationOnMainThread];
|
||||
}
|
||||
|
||||
@synchronized(self.lock) {
|
||||
if (self.completed) {
|
||||
return;
|
||||
}
|
||||
[self.condition lock];
|
||||
}
|
||||
while (!self.completed) {
|
||||
[self.condition wait];
|
||||
}
|
||||
[self.condition unlock];
|
||||
}
|
||||
|
||||
#pragma mark - NSObject
|
||||
|
||||
- (NSString *)description {
|
||||
// Acquire the data from the locked properties
|
||||
BOOL completed;
|
||||
BOOL cancelled;
|
||||
BOOL faulted;
|
||||
NSString *resultDescription = nil;
|
||||
|
||||
@synchronized(self.lock) {
|
||||
completed = self.completed;
|
||||
cancelled = self.cancelled;
|
||||
faulted = self.faulted;
|
||||
resultDescription = completed ? [NSString stringWithFormat:@" result = %@", self.result] : @"";
|
||||
}
|
||||
|
||||
// Description string includes status information and, if available, the
|
||||
// result since in some ways this is what a promise actually "is".
|
||||
return [NSString stringWithFormat:@"<%@: %p; completed = %@; cancelled = %@; faulted = %@;%@>",
|
||||
NSStringFromClass([self class]),
|
||||
self,
|
||||
completed ? @"YES" : @"NO",
|
||||
cancelled ? @"YES" : @"NO",
|
||||
faulted ? @"YES" : @"NO",
|
||||
resultDescription];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation OSSTask(OSS)
|
||||
|
||||
- (BOOL)isSuccessful {
|
||||
if (self.cancelled || self.faulted) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
- (NSError *)toError {
|
||||
if (self.cancelled) {
|
||||
return [NSError errorWithDomain:OSSClientErrorDomain
|
||||
code:OSSClientErrorCodeTaskCancelled
|
||||
userInfo:@{OSSErrorMessageTOKEN: @"This task is cancelled"}];
|
||||
} else if (self.error) {
|
||||
return self.error;
|
||||
} else if (self.exception) {
|
||||
return [NSError errorWithDomain:OSSClientErrorDomain
|
||||
code:OSSClientErrorCodeExcpetionCatched
|
||||
userInfo:@{OSSErrorMessageTOKEN: [NSString stringWithFormat:@"Catch exception - %@", self.exception]}];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (OSSTask *)completed:(OSSCompleteBlock)block {
|
||||
return [self continueWithBlock:^id _Nullable(OSSTask * _Nonnull task) {
|
||||
if ([task isSuccessful]) {
|
||||
block(YES, nil, task.result);
|
||||
} else {
|
||||
block(NO, [task toError], nil);
|
||||
}
|
||||
return nil;
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
89
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSTaskCompletionSource.h
generated
Normal file
89
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSTaskCompletionSource.h
generated
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class OSSTask<ResultType>;
|
||||
|
||||
/*!
|
||||
A OSSTaskCompletionSource represents the producer side of tasks.
|
||||
It is a task that also has methods for changing the state of the
|
||||
task by settings its completion values.
|
||||
*/
|
||||
@interface OSSTaskCompletionSource<__covariant ResultType> : NSObject
|
||||
|
||||
/*!
|
||||
Creates a new unfinished task.
|
||||
*/
|
||||
+ (instancetype)taskCompletionSource;
|
||||
|
||||
/*!
|
||||
The task associated with this TaskCompletionSource.
|
||||
*/
|
||||
@property (nonatomic, strong, readonly) OSSTask<ResultType> *task;
|
||||
|
||||
/*!
|
||||
Completes the task by setting the result.
|
||||
Attempting to set this for a completed task will raise an exception.
|
||||
@param result The result of the task.
|
||||
*/
|
||||
- (void)setResult:(nullable ResultType)result;
|
||||
|
||||
/*!
|
||||
Completes the task by setting the error.
|
||||
Attempting to set this for a completed task will raise an exception.
|
||||
@param error The error for the task.
|
||||
*/
|
||||
- (void)setError:(NSError *)error;
|
||||
|
||||
/*!
|
||||
Completes the task by setting an exception.
|
||||
Attempting to set this for a completed task will raise an exception.
|
||||
@param exception The exception for the task.
|
||||
*/
|
||||
- (void)setException:(NSException *)exception;
|
||||
|
||||
/*!
|
||||
Completes the task by marking it as cancelled.
|
||||
Attempting to set this for a completed task will raise an exception.
|
||||
*/
|
||||
- (void)cancel;
|
||||
|
||||
/*!
|
||||
Sets the result of the task if it wasn't already completed.
|
||||
@returns whether the new value was set.
|
||||
*/
|
||||
- (BOOL)trySetResult:(nullable ResultType)result;
|
||||
|
||||
/*!
|
||||
Sets the error of the task if it wasn't already completed.
|
||||
@param error The error for the task.
|
||||
@returns whether the new value was set.
|
||||
*/
|
||||
- (BOOL)trySetError:(NSError *)error;
|
||||
|
||||
/*!
|
||||
Sets the exception of the task if it wasn't already completed.
|
||||
@param exception The exception for the task.
|
||||
@returns whether the new value was set.
|
||||
*/
|
||||
- (BOOL)trySetException:(NSException *)exception;
|
||||
|
||||
/*!
|
||||
Sets the cancellation state of the task if it wasn't already completed.
|
||||
@returns whether the new value was set.
|
||||
*/
|
||||
- (BOOL)trySetCancelled;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
91
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSTaskCompletionSource.m
generated
Normal file
91
Pods/AliyunOSSiOS/AliyunOSSSDK/OSSTask/OSSTaskCompletionSource.m
generated
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#import "OSSTaskCompletionSource.h"
|
||||
|
||||
#import "OSSTask.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OSSTask (OSSTaskCompletionSource)
|
||||
|
||||
- (BOOL)trySetResult:(nullable id)result;
|
||||
- (BOOL)trySetError:(NSError *)error;
|
||||
- (BOOL)trySetException:(NSException *)exception;
|
||||
- (BOOL)trySetCancelled;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OSSTaskCompletionSource
|
||||
|
||||
#pragma mark - Initializer
|
||||
|
||||
+ (instancetype)taskCompletionSource {
|
||||
return [[self alloc] init];
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (!self) return self;
|
||||
|
||||
_task = [[OSSTask alloc] init];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Custom Setters/Getters
|
||||
|
||||
- (void)setResult:(nullable id)result {
|
||||
if (![self.task trySetResult:result]) {
|
||||
[NSException raise:NSInternalInconsistencyException
|
||||
format:@"Cannot set the result on a completed task."];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setError:(NSError *)error {
|
||||
if (![self.task trySetError:error]) {
|
||||
[NSException raise:NSInternalInconsistencyException
|
||||
format:@"Cannot set the error on a completed task."];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setException:(NSException *)exception {
|
||||
if (![self.task trySetException:exception]) {
|
||||
[NSException raise:NSInternalInconsistencyException
|
||||
format:@"Cannot set the exception on a completed task."];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)cancel {
|
||||
if (![self.task trySetCancelled]) {
|
||||
[NSException raise:NSInternalInconsistencyException
|
||||
format:@"Cannot cancel a completed task."];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)trySetResult:(nullable id)result {
|
||||
return [self.task trySetResult:result];
|
||||
}
|
||||
|
||||
- (BOOL)trySetError:(NSError *)error {
|
||||
return [self.task trySetError:error];
|
||||
}
|
||||
|
||||
- (BOOL)trySetException:(NSException *)exception {
|
||||
return [self.task trySetException:exception];
|
||||
}
|
||||
|
||||
- (BOOL)trySetCancelled {
|
||||
return [self.task trySetCancelled];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Reference in New Issue
Block a user