Popular Tags

Who's online

There are currently 0 users and 7 guests online.

User login

When dealing with concurrency on the Mac and iPhone, there are some nice classes available, such as NSLock, NSConditionLock and NSRecursiveLock. However, if you need to handle a producer-consumer model with multiple consumers of the same resource, then these locks by themselves won't quite suffice.

Below is the code for a counting semaphore. It is compliant with the NSLocking protocol and is implemented with two mutexes (binary semaphores) and an NSInteger. It will work in a garbage-collected environment.

//CHCountingLock.h
#import <Foundation/Foundation.h>
#import <pthread.h>
 
@interface CHCountingLock : NSObject <NSLocking> {
	pthread_mutex_t s1;
	pthread_mutex_t s2;
	NSInteger count;
}
 
- (id) initWithCount:(NSInteger)initialCount;
- (BOOL) tryLock;
 
@end
 
//CHCountingLock.m
#import "CHCountingLock.h"
 
@implementation CHCountingLock
 
- (id) init {
	return [self initWithCount:0];
}
 
- (id) initWithCount:(NSInteger)initialCount {
	if (self = [super init]) {
		pthread_mutex_init(&s1, NULL);
		pthread_mutex_init(&s2, NULL);
		pthread_mutex_lock(&s2);
		count = initialCount;
	}
	return self;
}
 
- (void) dealloc {
	pthread_mutex_destroy(&s1);
	pthread_mutex_destroy(&s2);
	[super dealloc];
}
 
- (void) finalize {
	pthread_mutex_destroy(&s1);
	pthread_mutex_destroy(&s2);
	[super finalize];
}
 
- (void) lock {
	pthread_mutex_lock(&s1);
	count--;
	if (count < 0) {
		pthread_mutex_unlock(&s1);
		pthread_mutex_lock(&s2);
	}
	pthread_mutex_unlock(&s1);
}
 
- (void) unlock {
	pthread_mutex_lock(&s1);
	count++;
	if (count <= 0) {
		pthread_mutex_unlock(&s2);
	} else {
		pthread_mutex_unlock(&s1);
	}
}
 
- (BOOL) tryLock {
	if (pthread_mutex_trylock(&s1) == 0) {
		count--;
		if (count < 0) {
			pthread_mutex_unlock(&s1);
			pthread_mutex_lock(&s2);
		}
		pthread_mutex_unlock(&s1);
		return YES;
	}
	return NO;
}
 
@end

Below is the code for a read/write lock. It is compliant with the NSLocking protocol and is a simple wrapper around a pthread_rwlock_t. It will work in a garbage-collected environment.

//CHReadWriteLock.h
#import <Foundation/Foundation.h>
#import <pthread.h>
 
@interface CHReadWriteLock : NSObject <NSLocking> {
	pthread_rwlock_t lock;
}
 
- (void) lockForWriting;
- (BOOL) tryLock;
- (BOOL) tryLockForWriting;
 
@end
 
//CHReadWriteLock.m
#import "CHReadWriteLock.h"
 
 
@implementation CHReadWriteLock
 
- (id) init {
	if (self = [super init]) {
		pthread_rwlock_init(&lock, NULL);
	}
	return self;
}
 
- (void) dealloc {
	pthread_rwlock_destroy(&lock);
	[super dealloc];
}
 
- (void) finalize {
	pthread_rwlock_destroy(&lock);
	[super finalize];
}
 
- (void) lock {
	pthread_rwlock_rdlock(&lock);
}
 
- (void) unlock {
	pthread_rwlock_unlock(&lock);
}
 
- (void) lockForWriting {
	pthread_rwlock_wrlock(&lock);
}
 
- (BOOL) tryLock {
	return (pthread_rwlock_tryrdlock(&lock) == 0);
}
 
- (BOOL) tryLockForWriting {
	return (pthread_rwlock_trywrlock(&lock) == 0);
}
 
@end

Your rating: None Average: 5 (2 votes)

Search

UPDATES

The site has recently been updated. You may notice some of the following issues:

  • Some URLs no longer work. Please use the search box.
  • File uploads should now be working. If you experience problems, please contact us.