Index: src/OFExceptions.h ================================================================== --- src/OFExceptions.h +++ src/OFExceptions.h @@ -1176,10 +1176,35 @@ * \brief An exception indicating that a mutex is still locked. */ @interface OFMutexLockedException: OFException @end +/** + * \brief An exception indicating waiting for a condition failed. + */ +@interface OFConditionWaitFailedException: OFException +@end + +/** + * \brief An exception indicating signalling a condition failed. + */ +@interface OFConditionSignalFailedException: OFException +@end + +/** + * \brief An exception indicating broadcasting a condition failed. + */ +@interface OFConditionBroadcastFailedException: OFException +@end + +/** + * \brief An exception indicating that a thread is still waiting for a + * condition. + */ +@interface OFConditionWaitingException: OFException +@end + /** * \brief An exception indicating that the hash has already been calculated. */ @interface OFHashAlreadyCalculatedException: OFException @end Index: src/OFExceptions.m ================================================================== --- src/OFExceptions.m +++ src/OFExceptions.m @@ -1716,10 +1716,63 @@ description = [[OFString alloc] initWithFormat: @"Deallocation of a mutex of type %@ was tried, even though it " @"was still locked!", inClass]; + return description; +} +@end + +@implementation OFConditionWaitFailedException +- (OFString*)description +{ + if (description != nil) + return description; + + description = [[OFString alloc] initWithFormat: + @"Waiting for a condition of type %@ failed!", inClass]; + + return description; +} +@end + +@implementation OFConditionSignalFailedException +- (OFString*)description +{ + if (description != nil) + return description; + + description = [[OFString alloc] initWithFormat: + @"Signaling a condition of type %@ failed!", inClass]; + + return description; +} +@end + +@implementation OFConditionBroadcastFailedException +- (OFString*)description +{ + if (description != nil) + return description; + + description = [[OFString alloc] initWithFormat: + @"Broadcasting a condition of type %@ failed!", inClass]; + + return description; +} +@end + +@implementation OFConditionWaitingException +- (OFString*)description +{ + if (description != nil) + return description; + + description = [[OFString alloc] initWithFormat: + @"Deallocation of a condition of type %@ was tried, even though a " + @"thread was still waiting for it!", inClass]; + return description; } @end @implementation OFHashAlreadyCalculatedException Index: src/OFThread.h ================================================================== --- src/OFThread.h +++ src/OFThread.h @@ -221,5 +221,36 @@ /** * Unlocks the mutex. */ - (void)unlock; @end + +/** + * \brief A class implementing a condition variable for thread synchronization. + */ +@interface OFCondition: OFMutex +{ + of_condition_t condition; + BOOL cond_initialized; +} + +/** + * \return A new, autoreleased OFCondition + */ ++ condition; + +/** + * Blocks the current thread until another thread calls -[signal] or + * -[broadcast]. + */ +- (void)wait; + +/** + * Signals the next waiting thread to continue. + */ +- (void)signal; + +/** + * Signals all threads to continue. + */ +- (void)broadcast; +@end Index: src/OFThread.m ================================================================== --- src/OFThread.m +++ src/OFThread.m @@ -370,8 +370,57 @@ { if (initialized) if (!of_mutex_free(&mutex)) @throw [OFMutexLockedException newWithClass: isa]; + [super dealloc]; +} +@end + +@implementation OFCondition ++ condition +{ + return [[[self alloc] init] autorelease]; +} + +- init +{ + self = [super init]; + + if (!of_condition_new(&condition)) { + Class c = isa; + [self release]; + @throw [OFInitializationFailedException newWithClass: c]; + } + + cond_initialized = YES; + + return self; +} + +- (void)wait +{ + if (!of_condition_wait(&condition, &mutex)) + @throw [OFConditionWaitFailedException newWithClass: isa]; +} + +- (void)signal +{ + if (!of_condition_signal(&condition)) + @throw [OFConditionSignalFailedException newWithClass: isa]; +} + +- (void)broadcast +{ + if (!of_condition_broadcast(&condition)) + @throw [OFConditionBroadcastFailedException newWithClass: isa]; +} + +- (void)dealloc +{ + if (cond_initialized) + if (!of_condition_free(&condition)) + @throw [OFConditionWaitingException newWithClass: isa]; + [super dealloc]; } @end