/*
 *
 * @APPLE_LICENSE_HEADER_START@
 *
 * Copyright (c) 1999-2001 Apple Computer, Inc.  All Rights Reserved. The
 * contents of this file constitute Original Code as defined in and are
 * subject to the Apple Public Source License Version 1.2 (the 'License').
 * You may not use this file except in compliance with the License.  Please
 * obtain a copy of the License at http://www.apple.com/publicsource and
 * read it before using this file.
 *
 * This Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.  Please
 * see the License for the specific language governing rights and
 * limitations under the License.
 *
 *
 * @APPLE_LICENSE_HEADER_END@
 *
 */
/*
	File:		OSCond.cpp

	Contains:	Implementation of OSCond class
	
	

*/

#include "OSCond.h"
#include "OSMutex.h"
#include "OSThread.h"
#include "MyAssert.h"

#if __PTHREADS_MUTEXES__
#include <sys/time.h>
#endif


OSCond::OSCond()
{
#ifdef __Win32__
	fCondition = ::CreateEvent(NULL, FALSE, FALSE, NULL);
	Assert(fCondition != NULL);
#elif __PTHREADS_MUTEXES__
	#if __MacOSX__
        int ret = pthread_cond_init(&fCondition, NULL);
        Assert(ret == 0);
	#else
		pthread_condattr_t cond_attr;
		pthread_condattr_init(&cond_attr);
		int ret = pthread_cond_init(&fCondition, &cond_attr);
		Assert(ret == 0);
	#endif
#else
	fCondition = mycondition_alloc();
	Assert(fCondition != NULL);
#endif
}

OSCond::~OSCond()
{
#ifdef __Win32__
	BOOL theErr = ::CloseHandle(fCondition);
	Assert(theErr == TRUE);
#elif __PTHREADS_MUTEXES__
	pthread_cond_destroy(&fCondition);
#else
	Assert(fCondition != NULL);
	mycondition_free(fCondition);
#endif
}

#if __PTHREADS_MUTEXES__
void OSCond::TimedWait(OSMutex* inMutex, SInt32 inTimeoutInMilSecs)
{
	struct timespec ts;
	struct timeval tv;
	struct timezone tz;
	int	sec, usec;
	
	//These platforms do refcounting manually, and wait will release the mutex,
	// so we need to update the counts here

	inMutex->fHolderCount--;
	inMutex->fHolder = 0;

	
	if (inTimeoutInMilSecs == 0)
		(void)pthread_cond_wait(&fCondition, &inMutex->fMutex);
	else
	{
		gettimeofday(&tv, &tz);
		sec = inTimeoutInMilSecs / 1000;
		inTimeoutInMilSecs = inTimeoutInMilSecs - (sec * 1000);
		Assert(inTimeoutInMilSecs < 1000);
		usec = inTimeoutInMilSecs * 1000;
		Assert(tv.tv_usec < 1000000);
		ts.tv_sec = tv.tv_sec + sec;
		ts.tv_nsec = (tv.tv_usec + usec) * 1000;
		Assert(ts.tv_nsec < 2000000000);
		if(ts.tv_nsec > 999999999)
		{
		     ts.tv_sec++;
		     ts.tv_nsec -= 1000000000;
		}
		(void)pthread_cond_timedwait(&fCondition, &inMutex->fMutex, &ts);
	}


	inMutex->fHolderCount++;
	inMutex->fHolder = pthread_self();
	
}
#endif
