// Copyright 1997-1999 Omni Development, Inc.  All rights reserved.
//
// This software may only be used and reproduced according to the
// terms in the file OmniSourceLicense.html, which should be
// distributed with this project and can also be found at
// http://www.omnigroup.com/DeveloperResources/OmniSourceLicense.html.

#import "OFCondition.h"

#import <Foundation/Foundation.h>
#import <OmniBase/OmniBase.h>

RCS_ID("$Header: /Network/Developer/Source/CVS/OmniGroup/OmniFoundation/OFCondition.m,v 1.6 1999/03/30 21:25:29 kc Exp $")

@implementation OFCondition

#ifdef FAST_BUGGY_WAY

- init;
{
    if (![super init])
        return nil;

    mutex_init(&machMutex);
    condition_init(&machCondition);
    signalCount = 0;

    return self;
}

- (void)dealloc;
{
    [self clearCondition];
    [super dealloc];
}

- (void)waitForCondition;
{
    unsigned int currentCount;
    
    mutex_lock(&machMutex);
    currentCount = signalCount;
    while (currentCount == signalCount)
        condition_wait(&machCondition, &machMutex);
    mutex_unlock(&machMutex);
}

- (void)signalCondition;
{
    mutex_lock(&machMutex);
    signalCount++;
    mutex_unlock(&machMutex);
    condition_signal(&machCondition);        
}

- (void)broadcastCondition;
{
    mutex_lock(&machMutex);
    signalCount++;
    mutex_unlock(&machMutex);
    condition_broadcast(&machCondition);
}

- (void)clearCondition;
{
    mutex_lock(&machMutex);
    signalCount++;
    mutex_unlock(&machMutex);
    condition_clear(&machCondition);
    mutex_clear(&machMutex);
}

#else

- init;
{
    if (![super init])
        return nil;

    lock = [[NSConditionLock alloc] init];
    flags.cleared = NO;

    return self;
}

- (void)dealloc;
{
    [lock release];
    [super dealloc];
}

- (void)waitForCondition;
{
    if (flags.cleared)
        return;
    [lock lockWhenCondition:1];
    if (!flags.cleared) {
        // TODO: If anyone else is waiting on this condition (say, if two data cursors are reading from the same data stream), they'll hang here until -clearCondition is called because we just reset their condition.
        [lock unlockWithCondition:0];
    } else {
        [lock unlock];
    }
}

- (void)signalCondition;
{
    [lock lock];
    [lock unlockWithCondition:1];
}

- (void)broadcastCondition;
{
    [lock lock];
    [lock unlockWithCondition:1];
}

- (void)clearCondition;
{
    flags.cleared = YES;
    [lock lock];
    [lock unlockWithCondition:1];
}

#endif

@end
