123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- //
- // QNSingleFlight.m
- // QiniuSDK
- //
- // Created by yangsen on 2021/1/4.
- // Copyright © 2021 Qiniu. All rights reserved.
- //
- #import "QNDefine.h"
- #import "QNSingleFlight.h"
- @interface QNSingleFlightTask : NSObject
- @property(nonatomic, copy)QNSingleFlightComplete complete;
- @end
- @implementation QNSingleFlightTask
- @end
- @interface QNSingleFlightCall : NSObject
- @property(nonatomic, assign)BOOL isComplete;
- @property(nonatomic, strong)NSMutableArray <QNSingleFlightTask *> *tasks;
- @property(nonatomic, strong)id value;
- @property(nonatomic, strong)NSError *error;
- @end
- @implementation QNSingleFlightCall
- @end
- @interface QNSingleFlight()
- @property(nonatomic, strong)NSMutableDictionary <NSString *, QNSingleFlightCall *> *callInfo;
- @end
- @implementation QNSingleFlight
- - (void)perform:(NSString * _Nullable)key
- action:(QNSingleFlightAction _Nonnull)action
- complete:(QNSingleFlightComplete _Nullable)complete {
- if (!action) {
- return;
- }
- BOOL isFirstTask = false;
- BOOL shouldComplete = false;
- QNSingleFlightCall *call = nil;
- @synchronized (self) {
- if (!self.callInfo) {
- self.callInfo = [NSMutableDictionary dictionary];
- }
-
- if (key) {
- call = self.callInfo[key];
- }
-
- if (!call) {
- call = [[QNSingleFlightCall alloc] init];
- call.isComplete = false;
- call.tasks = [NSMutableArray array];
- if (key) {
- self.callInfo[key] = call;
- }
- isFirstTask = true;
- }
-
- @synchronized (call) {
- shouldComplete = call.isComplete;
- if (!shouldComplete) {
- QNSingleFlightTask *task = [[QNSingleFlightTask alloc] init];
- task.complete = complete;
- [call.tasks addObject:task];
- }
- }
- }
-
- if (shouldComplete) {
- if (complete) {
- complete(call.value, call.error);
- }
- return;
- }
- if (!isFirstTask) {
- return;
- }
-
- kQNWeakSelf;
- kQNWeakObj(call);
- action(^(id value, NSError *error){
- kQNStrongSelf;
- kQNStrongObj(call);
-
- NSArray *tasksP = nil;
- @synchronized (call) {
- if (call.isComplete) {
- return;
- }
- call.isComplete = true;
- call.value = value;
- call.error = error;
- tasksP = [call.tasks copy];
- }
-
- if (key) {
- @synchronized (self) {
- [self.callInfo removeObjectForKey:key];
- }
- }
-
- for (QNSingleFlightTask *task in tasksP) {
- if (task.complete) {
- task.complete(value, error);
- }
- }
- });
- }
- @end
|