Skip to content

Commit ba0a1d5

Browse files
committed
Added STNetTaskGroup for executing tasks serially or concurrently.
Deprecated STNetTaskChain. Use @Class directive instead of #import in some header files.
1 parent 7844b14 commit ba0a1d5

File tree

11 files changed

+410
-17
lines changed

11 files changed

+410
-17
lines changed

STNetTaskQueue.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
76012C791C265EC50090BE94 /* STNetTaskQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 76012C6B1C265EC50090BE94 /* STNetTaskQueue.m */; };
2222
76012C7A1C265EC50090BE94 /* STNetTaskQueueLog.h in Headers */ = {isa = PBXBuildFile; fileRef = 76012C6C1C265EC50090BE94 /* STNetTaskQueueLog.h */; };
2323
76012C7B1C265EC50090BE94 /* STNetTaskQueueLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 76012C6D1C265EC50090BE94 /* STNetTaskQueueLog.m */; };
24+
7645D0FF1CDF66D5000ED54A /* STNetTaskGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 7645D0FD1CDF66D5000ED54A /* STNetTaskGroup.h */; settings = {ATTRIBUTES = (Public, ); }; };
25+
7645D1001CDF66D5000ED54A /* STNetTaskGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 7645D0FE1CDF66D5000ED54A /* STNetTaskGroup.m */; };
2426
/* End PBXBuildFile section */
2527

2628
/* Begin PBXFileReference section */
@@ -40,6 +42,8 @@
4042
76012C6B1C265EC50090BE94 /* STNetTaskQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STNetTaskQueue.m; sourceTree = "<group>"; };
4143
76012C6C1C265EC50090BE94 /* STNetTaskQueueLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STNetTaskQueueLog.h; sourceTree = "<group>"; };
4244
76012C6D1C265EC50090BE94 /* STNetTaskQueueLog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STNetTaskQueueLog.m; sourceTree = "<group>"; };
45+
7645D0FD1CDF66D5000ED54A /* STNetTaskGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STNetTaskGroup.h; sourceTree = "<group>"; };
46+
7645D0FE1CDF66D5000ED54A /* STNetTaskGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STNetTaskGroup.m; sourceTree = "<group>"; };
4347
/* End PBXFileReference section */
4448

4549
/* Begin PBXFrameworksBuildPhase section */
@@ -81,6 +85,8 @@
8185
76012C6B1C265EC50090BE94 /* STNetTaskQueue.m */,
8286
76012C6C1C265EC50090BE94 /* STNetTaskQueueLog.h */,
8387
76012C6D1C265EC50090BE94 /* STNetTaskQueueLog.m */,
88+
7645D0FD1CDF66D5000ED54A /* STNetTaskGroup.h */,
89+
7645D0FE1CDF66D5000ED54A /* STNetTaskGroup.m */,
8490
76012C5A1C265A160090BE94 /* Info.plist */,
8591
);
8692
path = STNetTaskQueue;
@@ -110,6 +116,7 @@
110116
76012C761C265EC50090BE94 /* STNetTaskChain.h in Headers */,
111117
76012C741C265EC50090BE94 /* STNetTask.h in Headers */,
112118
76012C781C265EC50090BE94 /* STNetTaskQueue.h in Headers */,
119+
7645D0FF1CDF66D5000ED54A /* STNetTaskGroup.h in Headers */,
113120
76012C721C265EC50090BE94 /* STHTTPNetTaskQueueHandler.h in Headers */,
114121
76012C7A1C265EC50090BE94 /* STNetTaskQueueLog.h in Headers */,
115122
76012C701C265EC50090BE94 /* STHTTPNetTaskParametersPacker.h in Headers */,
@@ -184,6 +191,7 @@
184191
buildActionMask = 2147483647;
185192
files = (
186193
76012C6F1C265EC50090BE94 /* STHTTPNetTask.m in Sources */,
194+
7645D1001CDF66D5000ED54A /* STNetTaskGroup.m in Sources */,
187195
76012C7B1C265EC50090BE94 /* STNetTaskQueueLog.m in Sources */,
188196
76012C711C265EC50090BE94 /* STHTTPNetTaskParametersPacker.m in Sources */,
189197
76012C771C265EC50090BE94 /* STNetTaskChain.m in Sources */,

STNetTaskQueue/STHTTPNetTaskParametersPacker.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
// Copyright (c) 2014 Sth4Me. All rights reserved.
77
//
88

9-
#import <STNetTaskQueue/STHTTPNetTask.h>
9+
#import <Foundation/Foundation.h>
10+
11+
@class STHTTPNetTask;
1012

1113
@interface STHTTPNetTaskParametersPacker : NSObject
1214

STNetTaskQueue/STHTTPNetTaskParametersPacker.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//
88

99
#import "STHTTPNetTaskParametersPacker.h"
10+
#import "STHTTPNetTask.h"
1011
#import <objc/runtime.h>
1112

1213
@implementation STHTTPNetTaskParametersPacker

STNetTaskQueue/STNetTask.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ @interface STNetTask ()
1616
@property (atomic, assign) BOOL cancelled;
1717
@property (atomic, assign) BOOL finished;
1818
@property (atomic, assign) NSUInteger retryCount;
19-
@property (nonatomic, strong) NSMutableDictionary<NSNumber *, NSMutableArray *> *stateToBlock;
19+
@property (nonatomic, strong) NSMutableDictionary<NSNumber *, NSMutableArray<STNetTaskSubscriptionBlock> *> *stateToBlock;
2020

2121
@end
2222

STNetTaskQueue/STNetTaskChain.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,19 @@
77
//
88

99
#import <Foundation/Foundation.h>
10-
#import <STNetTaskQueue/STNetTaskQueue.h>
1110

11+
@class STNetTaskQueue;
12+
@class STNetTask;
1213
@class STNetTaskChain;
1314

15+
DEPRECATED_MSG_ATTRIBUTE("Use STNetTaskGroup instead")
1416
@protocol STNetTaskChainDelegate <NSObject>
1517

1618
- (void)netTaskChainDidEnd:(STNetTaskChain *)netTaskChain;
1719

1820
@end
1921

22+
DEPRECATED_MSG_ATTRIBUTE("Use STNetTaskGroup instead")
2023
@interface STNetTaskChain : NSObject
2124

2225
@property (nonatomic, weak) id<STNetTaskChainDelegate> delegate;

STNetTaskQueue/STNetTaskChain.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
//
88

99
#import "STNetTaskChain.h"
10+
#import "STNetTask.h"
11+
#import "STNetTaskQueue.h"
1012

1113
@interface STNetTaskChain()<STNetTaskDelegate>
1214

STNetTaskQueue/STNetTaskGroup.h

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
//
2+
// STNetTaskGroup.h
3+
// STNetTaskQueue
4+
//
5+
// Created by Kevin Lin on 8/5/16.
6+
// Copyright © 2016 Sth4Me. All rights reserved.
7+
//
8+
9+
#import <Foundation/Foundation.h>
10+
11+
@class STNetTask;
12+
@class STNetTaskQueue;
13+
@class STNetTaskGroup;
14+
15+
typedef NS_ENUM(NSUInteger, STNetTaskGroupMode) {
16+
STNetTaskGroupModeSerial,
17+
STNetTaskGroupModeConcurrent
18+
};
19+
20+
typedef NS_ENUM(NSUInteger, STNetTaskGroupState) {
21+
STNetTaskGroupStateCancelled,
22+
STNetTaskGroupStateFinished
23+
};
24+
25+
/**
26+
@param group STNetTaskGroup
27+
@param error NSError the first error was encountered in the group.
28+
*/
29+
typedef void (^STNetTaskGroupSubscriptionBlock)(STNetTaskGroup *group, NSError *error);
30+
31+
/**
32+
STNetTaskGroup is a group to execute STNetTasks in serial or concurrent mode.
33+
NOTE: STNetTaskGroup is currently not thread safe.
34+
*/
35+
@interface STNetTaskGroup : NSObject
36+
37+
/**
38+
The executing task in the group when it is in STNetTaskGroupModeSerial.
39+
It will be always 'nil' when the group is in STNetTaskGroupModeConcurrent.
40+
*/
41+
@property (nonatomic, strong, readonly) STNetTask *executingTask;
42+
43+
/**
44+
All tasks in this group.
45+
*/
46+
@property (nonatomic, strong, readonly) NSArray<STNetTask *> *tasks;
47+
48+
/**
49+
The STNetTaskGroupMode is being used.
50+
*/
51+
@property (nonatomic, assign, readonly) STNetTaskGroupMode mode;
52+
53+
/**
54+
Indicates if the group is executing tasks.
55+
*/
56+
@property (nonatomic, assign, readonly) BOOL pending;
57+
58+
/**
59+
Init with an array of net tasks and mode.
60+
[STNetTaskQueue sharedQueue] will be used for executing tasks in the group.
61+
62+
@param tasks NSArray
63+
@param mode STNetTaskGroupMode indicates the tasks in this group should be sent serially or concurrently.
64+
*/
65+
- (instancetype)initWithTasks:(NSArray<STNetTask *> *)tasks mode:(STNetTaskGroupMode)mode;
66+
67+
/**
68+
Init with an array of net tasks, mode and the queue which will be used for executing tasks.
69+
70+
@param tasks NSArray
71+
@param mode STNetTaskGroupMode indicates the tasks in this group should be sent serially or concurrently.
72+
@param queue STNetTaskQueue the queue which is used for executing tasks in the group.
73+
*/
74+
- (instancetype)initWithTasks:(NSArray<STNetTask *> *)tasks mode:(STNetTaskGroupMode)mode queue:(STNetTaskQueue *)queue NS_DESIGNATED_INITIALIZER;
75+
76+
- (instancetype)init NS_UNAVAILABLE;
77+
78+
/**
79+
Add a new task to this group.
80+
81+
@param task STNetTask
82+
*/
83+
- (void)addTask:(STNetTask *)task;
84+
85+
/**
86+
Subscribe state with STNetTaskGroupSubscriptionBlock.
87+
88+
@param state STNetTaskGroupState
89+
@param block STNetTaskGroupSubscriptionBlock
90+
*/
91+
- (void)subscribeState:(STNetTaskGroupState)state usingBlock:(STNetTaskGroupSubscriptionBlock)block;
92+
93+
/**
94+
Start executing tasks in this group.
95+
*/
96+
- (void)start;
97+
98+
/**
99+
Cancel all tasks in this group.
100+
*/
101+
- (void)cancel;
102+
103+
@end
104+
105+
/**
106+
Handy category for executing tasks in an array.
107+
*/
108+
@interface NSArray (STNetTaskGroup)
109+
110+
- (STNetTaskGroup *)serialNetTaskGroup;
111+
- (STNetTaskGroup *)serialNetTaskGroupInQueue:(STNetTaskQueue *)queue;
112+
- (STNetTaskGroup *)concurrentNetTaskGroup;
113+
- (STNetTaskGroup *)concurrentNetTaskGroupInQueue:(STNetTaskQueue *)queue;
114+
115+
@end

STNetTaskQueue/STNetTaskGroup.m

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
//
2+
// STNetTaskGroup.m
3+
// STNetTaskQueue
4+
//
5+
// Created by Kevin Lin on 8/5/16.
6+
// Copyright © 2016 Sth4Me. All rights reserved.
7+
//
8+
9+
#import "STNetTaskGroup.h"
10+
#import "STNetTaskQueue.h"
11+
12+
@interface STNetTaskGroup ()
13+
14+
@property (nonatomic, strong) STNetTask *executingTask;
15+
@property (nonatomic, strong) NSArray<STNetTask *> *tasks;
16+
@property (nonatomic, assign) BOOL pending;
17+
@property (nonatomic, assign) BOOL started;
18+
@property (nonatomic, strong) NSMutableDictionary<NSNumber *, NSMutableArray<STNetTaskGroupSubscriptionBlock> *> *stateToBlock;
19+
@property (nonatomic, strong) STNetTaskSubscriptionBlock taskSubscriptionBlock; // For serial mode
20+
@property (nonatomic, strong, readonly) STNetTaskQueue *queue;
21+
22+
@end
23+
24+
@implementation STNetTaskGroup
25+
26+
- (instancetype)initWithTasks:(NSArray<STNetTask *> *)tasks mode:(STNetTaskGroupMode)mode
27+
{
28+
return [self initWithTasks:tasks mode:mode queue:[STNetTaskQueue sharedQueue]];
29+
}
30+
31+
- (instancetype)initWithTasks:(NSArray<STNetTask *> *)tasks mode:(STNetTaskGroupMode)mode queue:(STNetTaskQueue *)queue
32+
{
33+
if (self = [super init]) {
34+
self.tasks = [NSArray arrayWithArray:tasks];
35+
_mode = mode;
36+
_queue = queue;
37+
}
38+
return self;
39+
}
40+
41+
- (void)addTask:(STNetTask *)task
42+
{
43+
NSMutableArray *tasks = [_tasks mutableCopy];
44+
[tasks addObject:task];
45+
self.tasks = [NSArray arrayWithArray:tasks];
46+
}
47+
48+
- (void)subscribeState:(STNetTaskGroupState)state usingBlock:(STNetTaskGroupSubscriptionBlock)block
49+
{
50+
if (!self.stateToBlock) {
51+
self.stateToBlock = [NSMutableDictionary new];
52+
}
53+
NSMutableArray *blocks = self.stateToBlock[@(state)];
54+
if (!blocks) {
55+
blocks = [NSMutableArray new];
56+
self.stateToBlock[@(state)] = blocks;
57+
}
58+
[blocks addObject:[block copy]];
59+
}
60+
61+
- (void)notifyState:(STNetTaskGroupState)state withError:(NSError *)error
62+
{
63+
NSMutableArray<STNetTaskGroupSubscriptionBlock> *blocks = self.stateToBlock[@(state)];
64+
for (STNetTaskSubscriptionBlock block in blocks) {
65+
block(self, error);
66+
}
67+
self.stateToBlock = nil;
68+
self.taskSubscriptionBlock = nil;
69+
}
70+
71+
- (void)start
72+
{
73+
NSAssert(!self.started, @"STNetTaskQueue can not be reused, please create a new instance.");
74+
if (self.pending) {
75+
return;
76+
}
77+
self.pending = YES;
78+
self.started = YES;
79+
80+
switch (self.mode) {
81+
case STNetTaskGroupModeSerial: {
82+
__block NSUInteger executingTaskIndex = 0;
83+
__weak STNetTaskGroup *weakSelf = self;
84+
self.taskSubscriptionBlock = ^{
85+
if (weakSelf.executingTask.error) {
86+
[weakSelf notifyState:STNetTaskGroupStateFinished withError:weakSelf.executingTask.error];
87+
return;
88+
}
89+
executingTaskIndex++;
90+
if (executingTaskIndex == weakSelf.tasks.count) {
91+
[weakSelf notifyState:STNetTaskGroupStateFinished withError:nil];
92+
}
93+
else {
94+
weakSelf.executingTask = weakSelf.tasks[executingTaskIndex];
95+
[weakSelf.queue addTask:weakSelf.executingTask];
96+
[weakSelf.executingTask subscribeState:STNetTaskStateFinished usingBlock:weakSelf.taskSubscriptionBlock];
97+
}
98+
};
99+
self.executingTask = self.tasks[executingTaskIndex];
100+
[self.queue addTask:self.executingTask];
101+
[self.executingTask subscribeState:STNetTaskStateFinished usingBlock:self.taskSubscriptionBlock];
102+
}
103+
break;
104+
case STNetTaskGroupModeConcurrent: {
105+
__block NSUInteger finishedTasksCount = 0;
106+
for (STNetTask *task in self.tasks) {
107+
[self.queue addTask:task];
108+
[task subscribeState:STNetTaskStateFinished usingBlock:^{
109+
if (task.error) {
110+
[self cancelTasks];
111+
[self notifyState:STNetTaskGroupStateFinished withError:task.error];
112+
return;
113+
}
114+
finishedTasksCount++;
115+
if (finishedTasksCount == self.tasks.count) {
116+
[self notifyState:STNetTaskGroupStateFinished withError:nil];
117+
}
118+
}];
119+
}
120+
}
121+
break;
122+
default:
123+
break;
124+
}
125+
}
126+
127+
- (void)cancel
128+
{
129+
if (!self.pending) {
130+
return;
131+
}
132+
133+
switch (self.mode) {
134+
case STNetTaskGroupModeSerial: {
135+
[self.queue cancelTask:self.executingTask];
136+
self.executingTask = nil;
137+
}
138+
break;
139+
case STNetTaskGroupModeConcurrent: {
140+
[self cancelTasks];
141+
}
142+
break;
143+
default:
144+
break;
145+
}
146+
[self notifyState:STNetTaskGroupStateCancelled withError:nil];
147+
}
148+
149+
- (void)cancelTasks
150+
{
151+
for (STNetTask *task in self.tasks) {
152+
if (task.pending) {
153+
[self.queue cancelTask:task];
154+
}
155+
}
156+
}
157+
158+
@end
159+
160+
@implementation NSArray (STNetTaskGroup)
161+
162+
- (STNetTaskGroup *)serialNetTaskGroup
163+
{
164+
return [[STNetTaskGroup alloc] initWithTasks:self mode:STNetTaskGroupModeSerial];
165+
}
166+
167+
- (STNetTaskGroup *)serialNetTaskGroupInQueue:(STNetTaskQueue *)queue
168+
{
169+
return [[STNetTaskGroup alloc] initWithTasks:self mode:STNetTaskGroupModeSerial queue:queue];
170+
}
171+
172+
- (STNetTaskGroup *)concurrentNetTaskGroup
173+
{
174+
return [[STNetTaskGroup alloc] initWithTasks:self mode:STNetTaskGroupModeConcurrent];
175+
}
176+
177+
- (STNetTaskGroup *)concurrentNetTaskGroupInQueue:(STNetTaskQueue *)queue
178+
{
179+
return [[STNetTaskGroup alloc] initWithTasks:self mode:STNetTaskGroupModeConcurrent queue:queue];
180+
}
181+
182+
@end

0 commit comments

Comments
 (0)