I'm developing a daemon to run tasks as files get dropped into a folder. When a 
new file is detected, a new operation gets put onto the daemon's operation 
queue. The operation launches a task and waits for it to finish, then the 
operation exits.

The issue I am seeing is that the operation queue appears to indiscriminately 
run operations as they are added to the queue, regardless of system resources, 
thus bringing the whole system to a crawl. I thought, from reading the 
documentation, that the queue would be intelligent about how many operations it 
would have running at the same time, depending on system resources such as 
number of cores and available memory. Since this doesn't seem to be the case, I 
have to assume something is not quite right with my implementation.

My question: how can I ensure that no more operations are launched at any one 
time than the system can handle? Also, is there a way to find out the number of 
cores on a machine so that I can set that as a hard limit of number of 
operations on an NSOperationQueue?

The code is meant for 10.6.0 or higher and runs with garbage collection on.

Here is an outline of how my code implements the daemon and the operations:

All the daemon itself does, really, is to fire up a single  directory watcher, 
which is where all the action takes place. It then waits until it is signaled 
for termination, at which point it tears down the directory watcher and exits.

The crucial part of main() in the daemon:

----------
directoryWatcher = [[ANDirectoryWatcher alloc] initWithOptionsBlaBlaBla...];

[directoryWatcher start];

while (1) {
        [[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]];
}

// Should never get here
[directoryWatcher stop];
----------

The directory watcher owns a single operation queue, to which it adds 
operations as new files arrive in the folder it watches:

----------
-(void) handleNewFileFoundNotification:(NSNotification *)notification
{
        NSString *sourcePath = [[notification userInfo] objectForKey:@"path"];
        
        NSFileManager *localFileManager=[[NSFileManager alloc] init];
        NSDirectoryEnumerator *dirEnum = [localFileManager 
enumeratorAtPath:sourcePath];
        
        NSString *file;
        while (file = [dirEnum nextObject]) {
                if ([[file pathExtension] isEqualToString: @"ext"]) {
                        NSString *filePath = [sourcePath 
stringByAppendingPathComponent:file];
                        // Process the document only if the path is new. 
Otherwise the document is already being processed.
                        if ( ! [self previouslyKnownPath:filePath] ) {
                                ANTaskLauncherOperation *operation = 
[[ANTaskLauncherOperation alloc] initWithSourceFileURL:[NSURL 
fileURLWithPath:filePath]
                                                                                
                                                                                
                                         ...other options...];
                                [self.operationInfo setValue:operation 
forKey:filePath];
                                [self.operationQueue addOperation:(NSOperation 
*)operation];
                        }
                }
        }       
}
----------

The task launcher operation contains only three methods:

- An init method that is passed the required info and sets up essential 
instance variables based on the arguments.
- The following two methods:

----------

- (void)completeOperation 
{
    [self willChangeValueForKey:@"isFinished"];
    [self willChangeValueForKey:@"isExecuting"];
        
    self.executing = NO;
    self.finished = YES;
        
    [self didChangeValueForKey:@"isExecuting"];
    [self didChangeValueForKey:@"isFinished"];  
}


-(void)main 
{
        fprintf(stdout, "%s Received file: \"%s\"\n", 
ANTaskLauncherCurrentTimeString(), 
self.sourceFileURL.path.lastPathComponent.UTF8String);
        fflush(stdout);
    NSTask *task = [[NSTask alloc] init];
    NSMutableArray *args = [NSMutableArray array];
        
        // Find path to binary
        Dl_info info;
        int errDlAddr = dladdr( (const void *)__func__, &info );
        if(errDlAddr == 0) {
                return;
        }
        char *exec_path = (char *)(info.dli_fname);
        
        NSString *executablePath = [NSString stringWithCString:exec_path 
encoding:NSUTF8StringEncoding];
        executablePath = [executablePath substringToIndex:executablePath.length 
- 1];
        
        NSString *sourceFileName = self.sourceFileURL.lastPathComponent;
        NSString *outputPath = [self.outputURL.path 
stringByAppendingPathComponent:sourceFileName];
        
        ...snip, adjusting outputPath some more...
        
    /* set arguments */
    [args addObject:@"-f"];
    [args addObject:self.sourceFileURL.path];
    ...snip more arguments...

    [task setLaunchPath:executablePath];
    [task setArguments:args];

        ...snip, making sure file has arrived completely before we continue...
        
        [task launch];
        [task waitUntilExit];
        
        [[NSNotificationCenter defaultCenter] 
postNotificationName:ANOperationCompletedNotification
                                                                                
                                object:self];
        
        [self completeOperation];       
}

----------

The ANOperationCompletedNotification is caught by the directory watcher, which 
performs some internal cleanup.


Any pointers as to why the operation queue doesn't appear to manage the 
spawning of operations according to available system resource appreciated.


- António

-----------------------------------------------------------
What you have inside you expresses itself through both your
choice of words and the level of energy you assign to them.
The more healed, whole and connected you feel inside,
the more healing your words will be.

--Rita Goswami
-----------------------------------------------------------


_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to