@@ -33,9 +33,9 @@ @interface PBGitRevList ()
33
33
@property (nonatomic , weak ) PBGitRepository *repository;
34
34
@property (nonatomic , strong ) PBGitRevSpecifier *currentRev;
35
35
36
- @property (nonatomic , strong ) NSMutableDictionary *commitCache;
36
+ @property (nonatomic , strong ) NSCache <GTOID *, PBGitCommit *> *commitCache;
37
37
38
- @property (nonatomic , strong ) NSThread *parseThread ;
38
+ @property (nonatomic , strong ) NSOperationQueue *operationQueue ;
39
39
40
40
@end
41
41
@@ -54,42 +54,55 @@ - (id) initWithRepository:(PBGitRepository *)repo rev:(PBGitRevSpecifier *)rev s
54
54
self.repository = repo;
55
55
self.currentRev = [rev copy ];
56
56
self.isGraphing = graph;
57
- self.commitCache = [NSMutableDictionary new ];
57
+ self.commitCache = [[NSCache alloc ] init ];
58
+ self.operationQueue = [[NSOperationQueue alloc ] init ];
59
+ self.operationQueue .maxConcurrentOperationCount = 1 ;
60
+ self.operationQueue .qualityOfService = NSQualityOfServiceUtility ;
58
61
59
62
return self;
60
63
}
61
64
62
-
63
- - (void ) loadRevisons
65
+ - (void )loadRevisonsWithCompletionBlock : (void (^)(void ))completionBlock
64
66
{
65
67
[self cancel ];
66
-
67
- self.parseThread = [[NSThread alloc ] initWithTarget: self selector: @selector (beginWalkWithSpecifier: ) object: self .currentRev];
68
- self.isParsing = YES ;
68
+
69
69
self.resetCommits = YES ;
70
- [self .parseThread start ];
70
+
71
+ NSBlockOperation *parseOperation = [[NSBlockOperation alloc ] init ];
72
+
73
+ __weak typeof (self) weakSelf = self;
74
+ __weak typeof (parseOperation) weakParseOperation = parseOperation;
75
+
76
+ [parseOperation addExecutionBlock: ^{
77
+ PBGitRepository *pbRepo = weakSelf.repository ;
78
+ GTRepository *repo = pbRepo.gtRepo ;
79
+
80
+ NSError *error = nil ;
81
+ GTEnumerator *enu = [[GTEnumerator alloc ] initWithRepository: repo error: &error];
82
+
83
+ [weakSelf setupEnumerator: enu forRevspec: weakSelf.currentRev];
84
+ [weakSelf addCommitsFromEnumerator: enu inPBRepo: pbRepo operation: weakParseOperation];
85
+ }];
86
+ [parseOperation setCompletionBlock: completionBlock];
87
+
88
+ [self .operationQueue addOperation: parseOperation];
71
89
}
72
90
73
91
74
92
- (void )cancel
75
93
{
76
- [self .parseThread cancel ];
77
- self.parseThread = nil ;
78
- self.isParsing = NO ;
94
+ [self .operationQueue cancelAllOperations ];
79
95
}
80
96
81
-
82
- - (void ) finishedParsing
97
+ - (BOOL )isParsing
83
98
{
84
- self.parseThread = nil ;
85
- self.isParsing = NO ;
99
+ return self.operationQueue .operationCount > 0 ;
86
100
}
87
101
88
102
89
- - (void ) updateCommits : (NSDictionary *) update
103
+ - (void ) updateCommits : (NSArray <PBGitCommit *> *) revisions operation : ( NSOperation *) operation
90
104
{
91
- NSArray *revisions = [update objectForKey: kRevListRevisionsKey ];
92
- if (!revisions || [revisions count ] == 0 )
105
+ if (!revisions || [revisions count ] == 0 || operation.cancelled )
93
106
return ;
94
107
95
108
if (self.resetCommits ) {
@@ -105,19 +118,6 @@ - (void) updateCommits:(NSDictionary *)update
105
118
[self didChange: NSKeyValueChangeInsertion valuesAtIndexes: indexes forKey: @" commits" ];
106
119
}
107
120
108
- - (void ) beginWalkWithSpecifier : (PBGitRevSpecifier*)rev
109
- {
110
- PBGitRepository *pbRepo = self.repository ;
111
- GTRepository *repo = pbRepo.gtRepo ;
112
-
113
- NSError *error = nil ;
114
- GTEnumerator *enu = [[GTEnumerator alloc ] initWithRepository: repo error: &error];
115
-
116
- [self setupEnumerator: enu forRevspec: rev];
117
-
118
- [self addCommitsFromEnumerator: enu inPBRepo: pbRepo];
119
- }
120
-
121
121
static BOOL hasParameter (NSMutableArray *parameters, NSString *paramName) {
122
122
NSUInteger index = NSNotFound ;
123
123
@@ -191,8 +191,7 @@ - (void) setupEnumerator:(GTEnumerator*)enumerator
191
191
192
192
}
193
193
194
- - (void ) addCommitsFromEnumerator : (GTEnumerator *)enumerator
195
- inPBRepo : (PBGitRepository*)pbRepo ;
194
+ - (void ) addCommitsFromEnumerator : (GTEnumerator *)enumerator inPBRepo : (PBGitRepository*)pbRepo operation : (NSOperation *)operation
196
195
{
197
196
PBGitGrapher *g = [[PBGitGrapher alloc ] initWithRepository: pbRepo];
198
197
__block NSDate *lastUpdate = [NSDate date ];
@@ -204,11 +203,15 @@ - (void) addCommitsFromEnumerator:(GTEnumerator *)enumerator
204
203
205
204
BOOL enumSuccess = FALSE ;
206
205
__block int num = 0 ;
207
- __block NSMutableArray *revisions = [NSMutableArray array ];
206
+ __block NSMutableArray <PBGitCommit *> *revisions = [NSMutableArray array ];
208
207
NSError *enumError = nil ;
209
208
GTOID *oid = nil ;
210
- while ((oid = [enumerator nextOIDWithSuccess: &enumSuccess error: &enumError]) && enumSuccess) {
209
+ while ((oid = [enumerator nextOIDWithSuccess: &enumSuccess error: &enumError]) && enumSuccess && !operation. cancelled ) {
211
210
dispatch_group_async (loadGroup, loadQueue, ^{
211
+ if (operation.cancelled ) {
212
+ return ;
213
+ }
214
+
212
215
PBGitCommit *newCommit = nil ;
213
216
PBGitCommit *cachedCommit = [self .commitCache objectForKey: oid];
214
217
if (cachedCommit) {
@@ -231,14 +234,17 @@ - (void) addCommitsFromEnumerator:(GTEnumerator *)enumerator
231
234
});
232
235
}
233
236
234
- if (++num % 100 == 0 ) {
235
- if ([[NSDate date ] timeIntervalSinceDate: lastUpdate] > 0.5 && ![[NSThread currentThread ] isCancelled ]) {
236
- dispatch_group_wait (decorateGroup, DISPATCH_TIME_FOREVER);
237
- NSDictionary *update = [NSDictionary dictionaryWithObjectsAndKeys: revisions, kRevListRevisionsKey , nil ];
238
- [self performSelectorOnMainThread: @selector (updateCommits: ) withObject: update waitUntilDone: NO ];
239
- revisions = [NSMutableArray array ];
240
- lastUpdate = [NSDate date ];
241
- }
237
+ if (++num % 100 == 0 && [[NSDate date ] timeIntervalSinceDate: lastUpdate] > 0.2 ) {
238
+ dispatch_group_wait (decorateGroup, DISPATCH_TIME_FOREVER);
239
+
240
+ NSArray <PBGitCommit *> *updatedRevisions = [revisions copy ];
241
+
242
+ dispatch_async (dispatch_get_main_queue (), ^{
243
+ [self updateCommits: updatedRevisions operation: operation];
244
+ });
245
+
246
+ [revisions removeAllObjects ];
247
+ lastUpdate = [NSDate date ];
242
248
}
243
249
});
244
250
}
@@ -249,12 +255,11 @@ - (void) addCommitsFromEnumerator:(GTEnumerator *)enumerator
249
255
dispatch_group_wait (decorateGroup, DISPATCH_TIME_FOREVER);
250
256
251
257
// Make sure the commits are stored before exiting.
252
- if (![[NSThread currentThread ] isCancelled ]) {
253
- NSDictionary *update = [NSDictionary dictionaryWithObjectsAndKeys: revisions, kRevListRevisionsKey , nil ];
254
- [self performSelectorOnMainThread: @selector (updateCommits: ) withObject: update waitUntilDone: YES ];
255
-
256
- [self performSelectorOnMainThread: @selector (finishedParsing ) withObject: nil waitUntilDone: NO ];
257
- }
258
+ NSArray <PBGitCommit *> *updatedRevisions = [revisions copy ];
259
+
260
+ dispatch_async (dispatch_get_main_queue (), ^{
261
+ [self updateCommits: updatedRevisions operation: operation];
262
+ });
258
263
}
259
264
260
265
@end
0 commit comments