@@ -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,54 @@ - (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
65
- (void ) loadRevisons
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
+
87
+ [self .operationQueue addOperation: parseOperation];
71
88
}
72
89
73
90
74
91
- (void )cancel
75
92
{
76
- [self .parseThread cancel ];
77
- self.parseThread = nil ;
78
- self.isParsing = NO ;
93
+ [self .operationQueue cancelAllOperations ];
79
94
}
80
95
81
-
82
- - (void ) finishedParsing
96
+ - (BOOL )isParsing
83
97
{
84
- self.parseThread = nil ;
85
- self.isParsing = NO ;
98
+ return self.operationQueue .operationCount > 0 ;
86
99
}
87
100
88
101
89
- - (void ) updateCommits : (NSDictionary *) update
102
+ - (void ) updateCommits : (NSArray <PBGitCommit *> *) revisions operation : ( NSOperation *) operation
90
103
{
91
- NSArray *revisions = [update objectForKey: kRevListRevisionsKey ];
92
- if (!revisions || [revisions count ] == 0 )
104
+ if (!revisions || [revisions count ] == 0 || operation.cancelled )
93
105
return ;
94
106
95
107
if (self.resetCommits ) {
@@ -105,19 +117,6 @@ - (void) updateCommits:(NSDictionary *)update
105
117
[self didChange: NSKeyValueChangeInsertion valuesAtIndexes: indexes forKey: @" commits" ];
106
118
}
107
119
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
120
static BOOL hasParameter (NSMutableArray *parameters, NSString *paramName) {
122
121
NSUInteger index = NSNotFound ;
123
122
@@ -191,8 +190,7 @@ - (void) setupEnumerator:(GTEnumerator*)enumerator
191
190
192
191
}
193
192
194
- - (void ) addCommitsFromEnumerator : (GTEnumerator *)enumerator
195
- inPBRepo : (PBGitRepository*)pbRepo ;
193
+ - (void ) addCommitsFromEnumerator : (GTEnumerator *)enumerator inPBRepo : (PBGitRepository*)pbRepo operation : (NSOperation *)operation
196
194
{
197
195
PBGitGrapher *g = [[PBGitGrapher alloc ] initWithRepository: pbRepo];
198
196
__block NSDate *lastUpdate = [NSDate date ];
@@ -204,11 +202,15 @@ - (void) addCommitsFromEnumerator:(GTEnumerator *)enumerator
204
202
205
203
BOOL enumSuccess = FALSE ;
206
204
__block int num = 0 ;
207
- __block NSMutableArray *revisions = [NSMutableArray array ];
205
+ __block NSMutableArray <PBGitCommit *> *revisions = [NSMutableArray array ];
208
206
NSError *enumError = nil ;
209
207
GTOID *oid = nil ;
210
- while ((oid = [enumerator nextOIDWithSuccess: &enumSuccess error: &enumError]) && enumSuccess) {
208
+ while ((oid = [enumerator nextOIDWithSuccess: &enumSuccess error: &enumError]) && enumSuccess && !operation. cancelled ) {
211
209
dispatch_group_async (loadGroup, loadQueue, ^{
210
+ if (operation.cancelled ) {
211
+ return ;
212
+ }
213
+
212
214
PBGitCommit *newCommit = nil ;
213
215
PBGitCommit *cachedCommit = [self .commitCache objectForKey: oid];
214
216
if (cachedCommit) {
@@ -231,14 +233,17 @@ - (void) addCommitsFromEnumerator:(GTEnumerator *)enumerator
231
233
});
232
234
}
233
235
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
- }
236
+ if (++num % 100 == 0 && [[NSDate date ] timeIntervalSinceDate: lastUpdate] > 0.2 ) {
237
+ dispatch_group_wait (decorateGroup, DISPATCH_TIME_FOREVER);
238
+
239
+ NSArray <PBGitCommit *> *updatedRevisions = [revisions copy ];
240
+
241
+ dispatch_async (dispatch_get_main_queue (), ^{
242
+ [self updateCommits: updatedRevisions operation: operation];
243
+ });
244
+
245
+ [revisions removeAllObjects ];
246
+ lastUpdate = [NSDate date ];
242
247
}
243
248
});
244
249
}
@@ -249,12 +254,11 @@ - (void) addCommitsFromEnumerator:(GTEnumerator *)enumerator
249
254
dispatch_group_wait (decorateGroup, DISPATCH_TIME_FOREVER);
250
255
251
256
// 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
- }
257
+ NSArray <PBGitCommit *> *updatedRevisions = [revisions copy ];
258
+
259
+ dispatch_async (dispatch_get_main_queue (), ^{
260
+ [self updateCommits: updatedRevisions operation: operation];
261
+ });
258
262
}
259
263
260
264
@end
0 commit comments