forked from ImageOptim/ImageOptim
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFilesQueue.m
More file actions
99 lines (80 loc) · 3.36 KB
/
FilesQueue.m
File metadata and controls
99 lines (80 loc) · 3.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#import "FilesQueue.h"
#import "File.h"
#import "DirWorker.h"
@interface FilesQueue ()
@property (strong) NSUserDefaults *defaults;
@end
@implementation FilesQueue {
NSOperationQueue *cpuQueue;
NSOperationQueue *fileIOQueue;
NSOperationQueue *dirWorkerQueue;
}
@synthesize isBusy;
- (instancetype)initWithCPUs:(NSInteger)cpus dirs:(NSInteger)dirs files:(NSInteger)fileops defaults:(NSUserDefaults*)defaults {
self = [super init];
if (self) {
self.defaults = defaults;
BOOL lowPriority = [defaults boolForKey:@"RunLowPriority"];
cpuQueue = [NSOperationQueue new];
cpuQueue.name = @"cpuQueue";
cpuQueue.maxConcurrentOperationCount = cpus?cpus:NSOperationQueueDefaultMaxConcurrentOperationCount;
dirWorkerQueue = [NSOperationQueue new];
dirWorkerQueue.name = @"dirWorkerQueue";
dirWorkerQueue.maxConcurrentOperationCount = dirs;
fileIOQueue = [NSOperationQueue new];
fileIOQueue.name = @"fileIOQueue";
fileIOQueue.maxConcurrentOperationCount = fileops?fileops:2;
if ([cpuQueue respondsToSelector:@selector(setQualityOfService:)]) {
cpuQueue.qualityOfService = lowPriority ? NSQualityOfServiceUtility : NSQualityOfServiceUserInitiated;
fileIOQueue.qualityOfService = lowPriority ? NSQualityOfServiceUtility : NSQualityOfServiceUserInitiated;
dirWorkerQueue.qualityOfService = NSQualityOfServiceUserInitiated;
}
[cpuQueue addObserver:self forKeyPath:@"operationCount" options:0 context:NULL];
[dirWorkerQueue addObserver:self forKeyPath:@"operationCount" options:0 context:NULL];
[fileIOQueue addObserver:self forKeyPath:@"operationCount" options:0 context:NULL];
}
return self;
}
- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"operationCount"]) {
NSOperationQueue *queue = object;
NSUInteger newCount = queue.operationCount;
BOOL wasBusy = self.isBusy;
if (!wasBusy && newCount) {
dispatch_async(dispatch_get_main_queue(), ^{
self.isBusy = YES;
});
} else if (wasBusy && !newCount) {
BOOL goingBusy = cpuQueue.operationCount > 0 || dirWorkerQueue.operationCount > 0 || fileIOQueue.operationCount > 0;
dispatch_async(dispatch_get_main_queue(), ^{
self.isBusy = goingBusy;
});
}
}
}
-(void)addFile:(File*)f {
[f enqueueWorkersInCPUQueue:cpuQueue fileIOQueue:fileIOQueue defaults:self.defaults];
}
-(void)addDirWorker:(DirWorker *)d {
[dirWorkerQueue addOperation:d];
}
-(NSNumber *)queueCount {
return @(cpuQueue.operationCount + dirWorkerQueue.operationCount + fileIOQueue.operationCount);
}
-(void)cleanup {
[dirWorkerQueue cancelAllOperations];
[fileIOQueue cancelAllOperations];
[cpuQueue cancelAllOperations];
}
-(void)wait {
// any queue may be re-filled while waiting for another queue. This is wonky :(
do {
[dirWorkerQueue waitUntilAllOperationsAreFinished];
[fileIOQueue waitUntilAllOperationsAreFinished];
[cpuQueue waitUntilAllOperationsAreFinished];
}
while (dirWorkerQueue.operationCount > 0 || fileIOQueue.operationCount > 0 || cpuQueue.operationCount > 0);
}
@end