pushdeer/ios/Prototype_version/Pods/PromiseKit/Sources/join.m
2021-12-23 00:19:55 +08:00

55 lines
2.0 KiB
Objective-C

@import Foundation.NSDictionary;
#import "AnyPromise+Private.h"
#import <libkern/OSAtomic.h>
@import Foundation.NSError;
@import Foundation.NSNull;
#import "PromiseKit.h"
#import <stdatomic.h>
/**
Waits on all provided promises.
`PMKWhen` rejects as soon as one of the provided promises rejects. `PMKJoin` waits on all provided promises, then rejects if any of those promises rejects, otherwise it fulfills with values from the provided promises.
- Returns: A new promise that resolves once all the provided promises resolve.
*/
AnyPromise *PMKJoin(NSArray *promises) {
if (promises == nil)
return [AnyPromise promiseWithValue:[NSError errorWithDomain:PMKErrorDomain code:PMKInvalidUsageError userInfo:@{NSLocalizedDescriptionKey: @"PMKJoin(nil)"}]];
if (promises.count == 0)
return [AnyPromise promiseWithValue:promises];
return [AnyPromise promiseWithResolverBlock:^(PMKResolver resolve) {
NSPointerArray *results = NSPointerArrayMake(promises.count);
__block atomic_int countdown = promises.count;
__block BOOL rejected = NO;
[promises enumerateObjectsUsingBlock:^(AnyPromise *promise, NSUInteger ii, BOOL *stop) {
[promise __pipe:^(id value) {
if (IsError(value)) {
rejected = YES;
}
//FIXME surely this isn't thread safe on multiple cores?
[results replacePointerAtIndex:ii withPointer:(__bridge void *)(value ?: [NSNull null])];
atomic_fetch_sub_explicit(&countdown, 1, memory_order_relaxed);
if (countdown == 0) {
if (!rejected) {
resolve(results.allObjects);
} else {
id userInfo = @{PMKJoinPromisesKey: promises};
id err = [NSError errorWithDomain:PMKErrorDomain code:PMKJoinError userInfo:userInfo];
resolve(err);
}
}
}];
(void) stop;
}];
}];
}