mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-25 21:17:03 +00:00
296 lines
6.8 KiB
Plaintext
296 lines
6.8 KiB
Plaintext
/*
|
||
* CPOperation.j
|
||
*
|
||
* Created by Johannes Fahrenkrug.
|
||
* Copyright 2009, Springenwerk.
|
||
*
|
||
* This library is free software; you can redistribute it and/or
|
||
* modify it under the terms of the GNU Lesser General Public
|
||
* License as published by the Free Software Foundation; either
|
||
* version 2.1 of the License, or (at your option) any later version.
|
||
*
|
||
* This library is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
* Lesser General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU Lesser General Public
|
||
* License along with this library; if not, write to the Free Software
|
||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||
*/
|
||
|
||
@import "CPArray.j"
|
||
@import "CPObject.j"
|
||
|
||
/*!
|
||
Operations receive very low priority for execution.
|
||
@global
|
||
@group CPOperationQueuePriority
|
||
*/
|
||
CPOperationQueuePriorityVeryLow = -8;
|
||
|
||
/*!
|
||
Operations receive low priority for execution.
|
||
@global
|
||
@group CPOperationQueuePriority
|
||
*/
|
||
CPOperationQueuePriorityLow = -4;
|
||
|
||
/*!
|
||
Operations receive normal priority for execution.
|
||
@global
|
||
@group CPOperationQueuePriority
|
||
*/
|
||
CPOperationQueuePriorityNormal = 0;
|
||
|
||
/*!
|
||
Operations receive high priority for execution.
|
||
@global
|
||
@group CPOperationQueuePriority
|
||
*/
|
||
CPOperationQueuePriorityHigh = 4;
|
||
|
||
/*!
|
||
Operations receive very high priority for execution.
|
||
@global
|
||
@group CPOperationQueuePriority
|
||
*/
|
||
CPOperationQueuePriorityVeryHigh = 8;
|
||
|
||
|
||
/*!
|
||
@class CPOperation
|
||
@brief Represents an operation that can be run in an CPOperationQueue
|
||
|
||
It should be subclassed an the subclass should implement its own main method to do the actual work.
|
||
*/
|
||
@implementation CPOperation : CPObject
|
||
{
|
||
CPArray operations;
|
||
BOOL _cancelled;
|
||
BOOL _executing;
|
||
BOOL _finished;
|
||
BOOL _ready;
|
||
int _queuePriority;
|
||
JSObject _completionFunction;
|
||
CPArray _dependencies;
|
||
}
|
||
|
||
- (void)main
|
||
{
|
||
// should be overridden in child class
|
||
}
|
||
|
||
- (id)init
|
||
{
|
||
self = [super init];
|
||
|
||
if (self)
|
||
{
|
||
_cancelled = NO;
|
||
_executing = NO;
|
||
_finished = NO;
|
||
_ready = YES;
|
||
_dependencies = [[CPArray alloc] init];
|
||
_queuePriority = CPOperationQueuePriorityNormal;
|
||
}
|
||
return self;
|
||
}
|
||
|
||
/*!
|
||
Starts the operation (runs the main method), sets all the status flags and runs the completion function if it's set
|
||
*/
|
||
- (void)start
|
||
{
|
||
if (!_cancelled)
|
||
{
|
||
[self willChangeValueForKey:@"isExecuting"];
|
||
_executing = YES;
|
||
[self didChangeValueForKey:@"isExecuting"];
|
||
[self main];
|
||
if (_completionFunction)
|
||
{
|
||
_completionFunction();
|
||
}
|
||
[self willChangeValueForKey:@"isExecuting"];
|
||
_executing = NO;
|
||
[self didChangeValueForKey:@"isExecuting"];
|
||
[self willChangeValueForKey:@"isFinished"];
|
||
_finished = YES;
|
||
[self didChangeValueForKey:@"isFinished"];
|
||
}
|
||
}
|
||
|
||
/*!
|
||
Indicates if this operation has been cancelled
|
||
@return if this operation has been cancelled
|
||
*/
|
||
- (BOOL)isCancelled
|
||
{
|
||
return _cancelled;
|
||
}
|
||
|
||
/*!
|
||
Indicates if this operation is currently executing
|
||
@return if this operation is currently executing
|
||
*/
|
||
- (BOOL)isExecuting
|
||
{
|
||
return _executing;
|
||
}
|
||
|
||
/*!
|
||
Indicates if this operation has finished running
|
||
@return if this operation has finished running
|
||
*/
|
||
- (BOOL)isFinished
|
||
{
|
||
return _finished;
|
||
}
|
||
|
||
/*!
|
||
Just added for Cocoa compatibility
|
||
@return always false
|
||
*/
|
||
- (BOOL)isConcurrent
|
||
{
|
||
return NO;
|
||
}
|
||
|
||
/*!
|
||
Indicates if this operation is ready to be executed. Takes the "isFinished" state of dependent operations into account
|
||
@return if this operation is ready to run
|
||
*/
|
||
- (BOOL)isReady
|
||
{
|
||
return _ready;
|
||
}
|
||
|
||
/*!
|
||
The JS function that should be run after the main method
|
||
@return JS function
|
||
*/
|
||
- (JSObject)completionFunction
|
||
{
|
||
return _completionFunction;
|
||
}
|
||
|
||
/*!
|
||
Sets the JS function that should be run after the main method
|
||
*/
|
||
- (void)setCompletionFunction:(JSObject)aJavaScriptFunction
|
||
{
|
||
_completionFunction = aJavaScriptFunction;
|
||
}
|
||
|
||
/*!
|
||
Makes the receiver dependent on the completion of the specified operation.
|
||
@param anOperation the operation that the receiver should depend on
|
||
*/
|
||
- (void)addDependency:(CPOperation)anOperation
|
||
{
|
||
[self willChangeValueForKey:@"dependencies"];
|
||
[anOperation addObserver:self
|
||
forKeyPath:@"isFinished"
|
||
options:(CPKeyValueObservingOptionNew)
|
||
context:NULL];
|
||
[_dependencies addObject:anOperation];
|
||
[self didChangeValueForKey:@"dependencies"];
|
||
[self _updateIsReadyState];
|
||
}
|
||
|
||
/*!
|
||
Removes the receiver’s dependence on the specified operation.
|
||
@param anOperation the operation that the receiver should no longer depend on
|
||
*/
|
||
- (void)removeDependency:(CPOperation)anOperation
|
||
{
|
||
[self willChangeValueForKey:@"dependencies"];
|
||
[_dependencies removeObject:anOperation];
|
||
[anOperation removeObserver:self
|
||
forKeyPath:@"isFinished"];
|
||
[self didChangeValueForKey:@"dependencies"];
|
||
[self _updateIsReadyState];
|
||
}
|
||
|
||
/*!
|
||
The operations that the receiver depends on
|
||
@return array of operations
|
||
*/
|
||
- (CPArray)dependencies
|
||
{
|
||
return _dependencies;
|
||
}
|
||
|
||
/*!
|
||
Just added for Cocoa compatibility, doesn't do anything
|
||
*/
|
||
- (void)waitUntilFinished
|
||
{
|
||
}
|
||
|
||
/*!
|
||
Advises the operation object that it should stop executing its task.
|
||
*/
|
||
- (void)cancel
|
||
{
|
||
[self willChangeValueForKey:@"isCancelled"];
|
||
_cancelled = YES;
|
||
[self didChangeValueForKey:@"isCancelled"];
|
||
}
|
||
|
||
/*!
|
||
Sets the priority of the operation when used in an operation queue.
|
||
@param priority the priority
|
||
*/
|
||
- (void)setQueuePriority:(int)priority
|
||
{
|
||
_queuePriority = priority;
|
||
}
|
||
|
||
/*!
|
||
The priority of the operation when used in an operation queue.
|
||
@return the priority
|
||
*/
|
||
- (int)queuePriority
|
||
{
|
||
return _queuePriority;
|
||
}
|
||
|
||
// We need to observe the "isFinished" key of our dependent operations so we can update our own "isReady" state
|
||
- (void)observeValueForKeyPath:(CPString)keyPath
|
||
ofObject:(id)object
|
||
change:(CPDictionary)change
|
||
context:(void)context
|
||
{
|
||
if (keyPath == @"isFinished")
|
||
{
|
||
[self _updateIsReadyState];
|
||
}
|
||
}
|
||
|
||
- (void)_updateIsReadyState
|
||
{
|
||
var newReady = YES;
|
||
if (_dependencies && [_dependencies count] > 0)
|
||
{
|
||
var i = 0;
|
||
for (i = 0; i < [_dependencies count]; i++)
|
||
{
|
||
if (![[_dependencies objectAtIndex:i] isFinished])
|
||
{
|
||
newReady = NO;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (newReady != _ready)
|
||
{
|
||
[self willChangeValueForKey:@"isReady"];
|
||
_ready = newReady;
|
||
[self didChangeValueForKey:@"isReady"];
|
||
}
|
||
}
|
||
|
||
@end
|