I have extended NSOperationQueue
to allow adding NSBlockOperation
with a specific NSString
as identifier.
The identifier value is held in a NSMutableArray
serving as a registry. This is how I implement the registry.
-(void)addOperation:(NSOperation *)operation withID:(NSString*)operationID
{
@synchronized(self.queueReference)
{
[self.queueReference addObject:operationID]; // <-- just a mutable array
}
[operation setCompletionBlock:^(){
@synchronized(self.queueReference) {
[self.queueReference removeObject:operationID];
}
}];
[self addOperation:operation];
}
Basically I am adding a completion block which is cleaning the registry when that particular operation has finished.
However, while this works, I am in need to add more granularity to the queue.
I only use the queue with block operation, and during the execution of the block I may send different NSNotification
to the listener depending how the execution went.
What I was trying to achieve:
A caller try to add a particular NSBlockOperation
with identifier to queue. If queue already has such identifier just don't add block, and the calling class set itself as listener.
What is missing ? Checking for the identifier is not enough, there may be case when the NSBlockOperation
already dispatched the NSNotification
but the completion block has not yet being called.
So the caller class ask the queue, which is saying the identifier exists in registry, and caller wrongly set itself for listening to a notification that will never arrive because it's already being sent.
The scenario would be instead: caller ask the queue, which is saying 'identifier is in registry' but NSNotification
is sent. And the caller put NSBlockOperation
to queue.
The check of registry is made by means of a simple method:
-(BOOL)hasOperationWithID:(NSString*)operationID
{
@synchronized(self.queueReference)
{
return [self.queueReference containsObject:operationID];
}
}
but at this point I have not much idea on how to extend such method. The code I am working on is kind of 'academic', it does not serve any particular purpose, it is just me trying to experiment. Therefore I have great flexibility within the code. But this is quite new subject to me, so please be as much specific as possible of any downside of suggested implementation.