Files
youle_app_ios/Pods/Qiniu/QiniuSDK/Transaction/QNTransactionManager.m

354 lines
9.5 KiB
Objective-C

//
// QNTransactionManager.m
// QiniuSDK
//
// Created by yangsen on 2020/4/1.
// Copyright © 2020 Qiniu. All rights reserved.
//
#import "QNDefine.h"
#import "QNTransactionManager.h"
//MARK: -- 事务对象
typedef NS_ENUM(NSInteger, QNTransactionType){
QNTransactionTypeNormal, // 普通类型事务,事务体仅会执行一次
QNTransactionTypeTime, // 定时事务,事务体会定时执行
};
@interface QNTransaction()
// 事务类型
@property(nonatomic, assign)QNTransactionType type;
// 定时任务执行时间间隔
@property(nonatomic, assign)NSInteger interval;
// 事务延后时间 单位:秒
@property(nonatomic, assign)NSInteger after;
// 事务执行时间 与事务管理者定时器时间相关联
@property(nonatomic, assign)double createTime;
// 执行次数
@property(nonatomic, assign)long executedCount;
// 下次执行时的时间戳
@property(nonatomic, assign)double nextExecutionTime;
// 事务名称
@property(nonatomic, copy)NSString *name;
// 事务执行体
@property(nonatomic, copy)void(^action)(void);
// 下一个需要处理的事务
@property(nonatomic, strong, nullable)QNTransaction *nextTransaction;
@end
@implementation QNTransaction
+ (instancetype)transaction:(NSString *)name
after:(NSInteger)after
action:(void (^)(void))action{
QNTransaction *transaction = [[QNTransaction alloc] init];
transaction.type = QNTransactionTypeNormal;
transaction.after = after;
transaction.name = name;
transaction.action = action;
transaction.executedCount = 0;
transaction.createTime = [[NSDate date] timeIntervalSince1970];
transaction.nextExecutionTime = transaction.createTime + after;
return transaction;
}
+ (instancetype)timeTransaction:(NSString *)name
after:(NSInteger)after
interval:(NSInteger)interval
action:(void (^)(void))action{
QNTransaction *transaction = [[QNTransaction alloc] init];
transaction.type = QNTransactionTypeTime;
transaction.after = after;
transaction.name = name;
transaction.interval = interval;
transaction.action = action;
transaction.executedCount = 0;
transaction.createTime = [[NSDate date] timeIntervalSince1970];
transaction.nextExecutionTime = transaction.createTime + after;
return transaction;
}
- (BOOL)shouldAction {
double currentTime = [[NSDate date] timeIntervalSince1970];
if (self.type == QNTransactionTypeNormal) {
return self.executedCount < 1 && currentTime >= self.nextExecutionTime;
} else if (self.type == QNTransactionTypeTime) {
return currentTime >= self.nextExecutionTime;
} else {
return NO;
}
}
- (BOOL)maybeCompleted {
if (self.type == QNTransactionTypeNormal) {
return self.executedCount > 0;
} else if (self.type == QNTransactionTypeTime) {
return false;
} else {
return false;
}
}
- (void)handleAction {
if (![self shouldAction]) {
return;
}
if (self.action) {
_isExecuting = YES;
self.executedCount += 1;
self.nextExecutionTime = [[NSDate date] timeIntervalSince1970] + self.interval;
self.action();
_isExecuting = NO;
}
}
@end
//MARK: -- 事务链表
@interface QNTransactionList : NSObject
@property(nonatomic, strong)QNTransaction *header;
@end
@implementation QNTransactionList
- (BOOL)isEmpty{
if (self.header == nil) {
return YES;
} else {
return NO;
}
}
- (NSArray <QNTransaction *> *)transactionsForName:(NSString *)name{
NSMutableArray *transactions = [NSMutableArray array];
[self enumerate:^(QNTransaction *transaction, BOOL * _Nonnull stop) {
if ((name == nil && transaction.name == nil)
|| (name != nil && transaction.name != nil && [transaction.name isEqualToString:name])) {
[transactions addObject:transaction];
}
}];
return [transactions copy];
}
- (void)enumerate:(void(^)(QNTransaction *transaction, BOOL * _Nonnull stop))handler {
if (!handler) {
return;
}
BOOL isStop = NO;
QNTransaction *transaction = self.header;
while (transaction && !isStop) {
handler(transaction, &isStop);
transaction = transaction.nextTransaction;
}
}
- (void)add:(QNTransaction *)transaction{
@synchronized (self) {
QNTransaction *transactionP = self.header;
while (transactionP.nextTransaction) {
transactionP = transactionP.nextTransaction;
}
if (transactionP) {
transactionP.nextTransaction = transaction;
} else {
self.header = transaction;
}
}
}
- (void)remove:(QNTransaction *)transaction{
@synchronized (self) {
QNTransaction *transactionP = self.header;
QNTransaction *transactionLast = nil;
while (transactionP) {
if (transactionP == transaction) {
if (transactionLast) {
transactionLast.nextTransaction = transactionP.nextTransaction;
} else {
self.header = transactionP.nextTransaction;
}
break;
}
transactionLast = transactionP;
transactionP = transactionP.nextTransaction;
}
}
}
- (BOOL)has:(QNTransaction *)transaction{
@synchronized (self) {
__block BOOL has = NO;
[self enumerate:^(QNTransaction *transactionP, BOOL * _Nonnull stop) {
if (transaction == transactionP) {
has = YES;
*stop = YES;
}
}];
return has;
}
}
- (void)removeAll{
@synchronized (self) {
self.header = nil;
}
}
@end
//MARK: -- 事务管理者
@interface QNTransactionManager()
// 事务处理线程
@property(nonatomic, strong)NSThread *thread;
// 事务链表
@property(nonatomic, strong)QNTransactionList *transactionList;
// 事务定时器
@property(nonatomic, strong)NSTimer *timer;
@end
@implementation QNTransactionManager
+ (instancetype)shared{
static QNTransactionManager *manager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[QNTransactionManager alloc] init];
});
return manager;
}
- (instancetype)init{
if (self = [super init]) {
_transactionList = [[QNTransactionList alloc] init];
}
return self;
}
- (NSArray <QNTransaction *> *)transactionsForName:(NSString *)name{
return [self.transactionList transactionsForName:name];
}
- (BOOL)existTransactionsForName:(NSString *)name{
NSArray *transactionList = [self transactionsForName:name];
if (transactionList && transactionList.count > 0) {
return YES;
} else {
return NO;
}
}
- (void)addTransaction:(QNTransaction *)transaction{
if (transaction == nil) {
return;
}
[self.transactionList add:transaction];
[self createThread];
}
- (void)removeTransaction:(QNTransaction *)transaction{
if (transaction == nil) {
return;
}
[self.transactionList remove:transaction];
}
- (void)performTransaction:(QNTransaction *)transaction{
if (transaction == nil) {
return;
}
@synchronized (self) {
if (![self.transactionList has:transaction]) {
[self.transactionList add:transaction];
}
transaction.createTime = [[NSDate date] timeIntervalSince1970] - transaction.interval;
}
}
/// 销毁资源
- (void)destroyResource{
@synchronized (self) {
[self invalidateTimer];
[self.thread cancel];
self.thread = nil;
[self.transactionList removeAll];
}
}
//MARK: -- handle transaction action
- (void)handleAllTransaction{
[self.transactionList enumerate:^(QNTransaction *transaction, BOOL * _Nonnull stop) {
[self handleTransaction:transaction];
if ([transaction maybeCompleted]) {
[self removeTransaction:transaction];
}
}];
}
- (void)handleTransaction:(QNTransaction *)transaction{
[transaction handleAction];
}
//MARK: -- thread
- (void)createThread{
@synchronized (self) {
if (self.thread == nil) {
kQNWeakSelf;
self.thread = [[NSThread alloc] initWithTarget:weak_self
selector:@selector(threadAction)
object:nil];
self.thread.name = @"com.qiniu.transaction";
[self.thread start];
}
}
}
- (void)threadAction{
@autoreleasepool {
if (self.timer == nil) {
[self createTimer];
}
NSThread *thread = [NSThread currentThread];
while (thread && !thread.isCancelled) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
}
}
}
//MARK: -- timer
- (void)createTimer{
kQNWeakSelf;
NSTimer *timer = [NSTimer timerWithTimeInterval:1
target:weak_self
selector:@selector(timerAction)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer
forMode:NSDefaultRunLoopMode];
[self timerAction];
_timer = timer;
}
- (void)invalidateTimer{
[self.timer invalidate];
self.timer = nil;
}
- (void)timerAction{
[self handleAllTransaction];
}
@end