Today, something pretty simple: An implementation of a threadsafe queue in Cocoa/Objective-C, suitable for use when implementing the producer-consumer pattern. Nothing too extraordinary: I use an NSMutableArray to store the data (object ids) and the pthreads library for synchronization.
Code
Here’s the header file:
#import <Foundation/Foundation.h>
@interface lockedQueue : NSObject {
pthread_mutex_t mx;
pthread_cond_t cv;
NSMutableArray* array;
}
- (void)enqueue:(id)object;
- (id)dequeue;
- (void)clear;
@end
and here’s the implementation:
#import <pthread.h>
#import "lockedQueue.h"
@implementation lockedQueue
- (id)init
{
if (self = [super init])
{
pthread_mutex_init(&mx, NULL);
pthread_cond_init(&cv, NULL);
array = [[NSMutableArray alloc] init];
}
return self;
}
- (void)enqueue:(id)object
{
pthread_mutex_lock(&mx);
[array insertObject:object atIndex:0];
pthread_cond_signal(&cv);
pthread_mutex_unlock(&mx);
}
- (id)dequeue
{
id rv;
pthread_mutex_lock(&mx);
while (![array count])
{
pthread_cond_wait(&cv, &mx);
}
rv = [[[array lastObject] retain] autorelease];
[array removeLastObject];
pthread_mutex_unlock(&mx);
return rv;
}
- (void)clear
{
pthread_mutex_lock(&mx);
[array removeAllObjects];
pthread_mutex_unlock(&mx);
}
- (void)dealloc
{
[array release];
[super dealloc];
}
@end
Things To Note
This code is pretty straight-forward; there are only a few minor twists:
- Every time an object is added to the queue, the condition variable is signaled. This will wake up at least one waiting thread (if there are any) to pull the new data off the queue; this guarantees that threads will never sleep when there is data for them to pull.
- Objects pulled from the queue are
retained
andautoreleased
before being deleted from the queue; if this were not done, they might be deallocated out from underneath thedequeue
function. - The
enqueue
anddequeue
functions manipulateids
, s.t. they can be used with objects of any type.