Skip to content

Commit 1e05f19

Browse files
authored
Merge pull request #92 from ksuther/nsoperation-for-gitrevlist
Switch to using NSOperation and NSOperationQueue in PBGitRevList
2 parents 03e354e + 75b2691 commit 1e05f19

File tree

3 files changed

+72
-59
lines changed

3 files changed

+72
-59
lines changed

Classes/git/PBGitHistoryList.m

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ - (void) updateCommitsFromGrapher:(NSDictionary *)commitData
135135

136136
- (void) finishedGraphing
137137
{
138-
if (!currentRevList.isParsing && ([[graphQueue operations] count] == 0)) {
138+
if (!currentRevList.parsing && ([[graphQueue operations] count] == 0)) {
139139
self.isUpdating = NO;
140140
}
141141
}
@@ -318,11 +318,14 @@ - (void) updateProjectHistoryForRev:(PBGitRevSpecifier *)rev
318318
lastRemoteRef = nil;
319319
lastOID = nil;
320320
self.commits = [NSMutableArray array];
321-
[projectRevList loadRevisons];
322-
return;
321+
[projectRevList loadRevisonsWithCompletionBlock:^{
322+
dispatch_async(dispatch_get_main_queue(), ^{
323+
[self finishedGraphing];
324+
});
325+
}];
326+
} else {
327+
[graphQueue addOperation:[self operationForCommits:projectRevList.commits]];
323328
}
324-
325-
[graphQueue addOperation:[self operationForCommits:projectRevList.commits]];
326329
}
327330

328331

@@ -337,7 +340,11 @@ - (void) updateHistoryForRev:(PBGitRevSpecifier *)rev
337340
lastOID = nil;
338341
self.commits = [NSMutableArray array];
339342

340-
[otherRevListParser loadRevisons];
343+
[otherRevListParser loadRevisonsWithCompletionBlock:^{
344+
dispatch_async(dispatch_get_main_queue(), ^{
345+
[self finishedGraphing];
346+
});
347+
}];
341348
}
342349

343350

Classes/git/PBGitRevList.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@
1010

1111
@class PBGitRepository;
1212
@class PBGitRevSpecifier;
13+
@class PBGitCommit;
1314

1415
@interface PBGitRevList : NSObject
1516

16-
@property (nonatomic, assign) BOOL isParsing;
17-
@property (nonatomic, strong) NSMutableArray *commits;
17+
@property (nonatomic, assign, getter=isParsing, readonly) BOOL parsing;
18+
@property (nonatomic, strong) NSMutableArray<PBGitCommit *> *commits;
1819

1920
- (id) initWithRepository:(PBGitRepository *)repo rev:(PBGitRevSpecifier *)rev shouldGraph:(BOOL)graph;
20-
- (void) loadRevisons;
21+
- (void)loadRevisonsWithCompletionBlock:(void(^)(void))completionBlock;
2122
- (void)cancel;
2223

2324
@end

Classes/git/PBGitRevList.mm

Lines changed: 55 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ @interface PBGitRevList ()
3333
@property (nonatomic, weak) PBGitRepository *repository;
3434
@property (nonatomic, strong) PBGitRevSpecifier *currentRev;
3535

36-
@property (nonatomic, strong) NSMutableDictionary *commitCache;
36+
@property (nonatomic, strong) NSCache<GTOID *, PBGitCommit *> *commitCache;
3737

38-
@property (nonatomic, strong) NSThread *parseThread;
38+
@property (nonatomic, strong) NSOperationQueue *operationQueue;
3939

4040
@end
4141

@@ -54,42 +54,55 @@ - (id) initWithRepository:(PBGitRepository *)repo rev:(PBGitRevSpecifier *)rev s
5454
self.repository = repo;
5555
self.currentRev = [rev copy];
5656
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;
5861

5962
return self;
6063
}
6164

62-
63-
- (void) loadRevisons
65+
- (void)loadRevisonsWithCompletionBlock:(void(^)(void))completionBlock
6466
{
6567
[self cancel];
66-
67-
self.parseThread = [[NSThread alloc] initWithTarget:self selector:@selector(beginWalkWithSpecifier:) object:self.currentRev];
68-
self.isParsing = YES;
68+
6969
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];
7189
}
7290

7391

7492
- (void)cancel
7593
{
76-
[self.parseThread cancel];
77-
self.parseThread = nil;
78-
self.isParsing = NO;
94+
[self.operationQueue cancelAllOperations];
7995
}
8096

81-
82-
- (void) finishedParsing
97+
- (BOOL)isParsing
8398
{
84-
self.parseThread = nil;
85-
self.isParsing = NO;
99+
return self.operationQueue.operationCount > 0;
86100
}
87101

88102

89-
- (void) updateCommits:(NSDictionary *)update
103+
- (void) updateCommits:(NSArray<PBGitCommit *> *)revisions operation:(NSOperation *)operation
90104
{
91-
NSArray *revisions = [update objectForKey:kRevListRevisionsKey];
92-
if (!revisions || [revisions count] == 0)
105+
if (!revisions || [revisions count] == 0 || operation.cancelled)
93106
return;
94107

95108
if (self.resetCommits) {
@@ -105,19 +118,6 @@ - (void) updateCommits:(NSDictionary *)update
105118
[self didChange:NSKeyValueChangeInsertion valuesAtIndexes:indexes forKey:@"commits"];
106119
}
107120

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-
121121
static BOOL hasParameter(NSMutableArray *parameters, NSString *paramName) {
122122
NSUInteger index = NSNotFound;
123123

@@ -191,8 +191,7 @@ - (void) setupEnumerator:(GTEnumerator*)enumerator
191191

192192
}
193193

194-
- (void) addCommitsFromEnumerator:(GTEnumerator *)enumerator
195-
inPBRepo:(PBGitRepository*)pbRepo;
194+
- (void) addCommitsFromEnumerator:(GTEnumerator *)enumerator inPBRepo:(PBGitRepository*)pbRepo operation:(NSOperation *)operation
196195
{
197196
PBGitGrapher *g = [[PBGitGrapher alloc] initWithRepository:pbRepo];
198197
__block NSDate *lastUpdate = [NSDate date];
@@ -204,11 +203,15 @@ - (void) addCommitsFromEnumerator:(GTEnumerator *)enumerator
204203

205204
BOOL enumSuccess = FALSE;
206205
__block int num = 0;
207-
__block NSMutableArray *revisions = [NSMutableArray array];
206+
__block NSMutableArray<PBGitCommit *> *revisions = [NSMutableArray array];
208207
NSError *enumError = nil;
209208
GTOID *oid = nil;
210-
while ((oid = [enumerator nextOIDWithSuccess:&enumSuccess error:&enumError]) && enumSuccess) {
209+
while ((oid = [enumerator nextOIDWithSuccess:&enumSuccess error:&enumError]) && enumSuccess && !operation.cancelled) {
211210
dispatch_group_async(loadGroup, loadQueue, ^{
211+
if (operation.cancelled) {
212+
return;
213+
}
214+
212215
PBGitCommit *newCommit = nil;
213216
PBGitCommit *cachedCommit = [self.commitCache objectForKey:oid];
214217
if (cachedCommit) {
@@ -231,14 +234,17 @@ - (void) addCommitsFromEnumerator:(GTEnumerator *)enumerator
231234
});
232235
}
233236

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];
242248
}
243249
});
244250
}
@@ -249,12 +255,11 @@ - (void) addCommitsFromEnumerator:(GTEnumerator *)enumerator
249255
dispatch_group_wait(decorateGroup, DISPATCH_TIME_FOREVER);
250256

251257
// 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+
});
258263
}
259264

260265
@end

0 commit comments

Comments
 (0)