#include "ostime.h"
#include "ossync.h"

LPSECURITY_ATTRIBUTES
DefaultSecurity::attributes()
{	
#ifdef _WIN32_
	static SECURITY_ATTRIBUTES defaultsa;
	static SECURITY_DESCRIPTOR sd;	
	InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
	SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
	defaultsa.nLength = sizeof(SECURITY_ATTRIBUTES);
	defaultsa.lpSecurityDescriptor = &sd;
	defaultsa.bInheritHandle = TRUE;	
	return &defaultsa;
#endif
return 0;
}
ThreadMutex::ThreadMutex()
{	
	init();
}
void ThreadMutex::init()
{
//TODO: throw exception if NULL
#ifdef _WIN32_
	::InitializeCriticalSection (&_synchandle); 
	//if (_mutex == 0)
		//throw exception      
#endif
#ifdef _VXWORKS_
	vxw_mutex_init(_synchandle);
#endif /* ! defined _WIN32_ */
}
int ThreadMutex::lock()
{
#ifdef _WIN32_
  init();
  ::EnterCriticalSection (&_synchandle);
  return 0;
#endif
#ifdef _VXWORKS_
    vxw_mutex_lock(_synchandle);
    return 0;
#endif 
  return -1;
}
int ThreadMutex::unlock()
{
#ifdef _WIN32_
  ::LeaveCriticalSection (&_synchandle);
  return 0;
#endif
#ifdef _VXWORKS_
  vxw_mutex_unlock(_synchandle);
  return 0;
#endif
return -1;
}

ThreadMutex::~ThreadMutex()
{
#ifdef _WIN32_
	//::CloseHandle (_synchandle);
	::DeleteCriticalSection(&_synchandle);
#endif
#ifdef _VXWORKS_
	vxw_mutex_fini(_synchandle);
#endif
}
THREAD_MUTEX_HANDLE *ThreadMutex::handle()
{
	return &_synchandle;
}

BinarySemaphore::BinarySemaphore(SEM_B_STATE initcount, const char *name)
{
#ifdef _WIN32_
	//The state of a semaphore is signaled when its count 
	//is greater than zero and nonsignaled when it is zero. 
	//The count is decreased by one whenever a wait function 
	//releases a thread that was waiting for the semaphore. 
	//The count is increased by a specified amount by calling the
	//ReleaseSemaphore function. 
	_synchandle  = ::CreateSemaphore (DefaultSecurity::attributes(),initcount, 1, name);
	//TODO: throw exception if NULL
	// add lpsecurity struct
#endif
#ifdef _VXWORKS_
	_synchandle = ::semBCreate (SEM_Q_FIFO, initcount);
#endif
}
SYNC_HANDLE *BinarySemaphore::handle()
{
	return &_synchandle;
}
BinarySemaphore::~BinarySemaphore()
{
#ifdef _WIN32_
	::CloseHandle (_synchandle);
#endif
#ifdef _VXWORKS_
	// throw exception == OK ? 0 : -1;
	::semDelete (_synchandle);	
#endif
}

int BinarySemaphore::semTake(int milliSeconds)
{
#ifdef _WIN32_	
  DWord result = ::WaitForSingleObject (_synchandle, milliSeconds);

  if (result == WAIT_OBJECT_0)
    return 0;
  else{
      return ( result == WAIT_TIMEOUT ? -1 : ::GetLastError ());
  }
#endif
#ifdef _VXWORKS_
  // Must return -1 on error!!!
  // couldn't get the BinarySemaphore
  int tcks; 
  if(milliSeconds != WAIT_FOREVER){
  tcks = (int)(milliSeconds * Clock::getSystemClkTck()/1000);
  }else
  tcks = WAIT_FOREVER;  
  if (::semTake (_synchandle, tcks) == ERROR)
      return -1;
 
   return 0;
#endif
}
int BinarySemaphore::semGive()
{
#ifdef _WIN32_
	return ::ReleaseSemaphore (_synchandle, 1, 0);
#endif
#ifdef _VXWORKS_
	return ::semGive (_synchandle);
#endif
return -1;
}
