// OISemaphore.cpp : implementation file
|
//
|
|
#include "stdafx.h"
|
#include "OISemaphore.h"
|
|
#include "OIThread.h"
|
|
namespace OIComm {
|
|
/////////////////////////////////////////////////////////////////////////////
|
// COISemaphore
|
|
OISemaphoreHandle COISemaphore::GetHandle()
|
{
|
return m_hSem;
|
}
|
|
// Windows ---------------------------------------------------------------
|
#ifdef _WIN32
|
|
COISemaphore::COISemaphore( oi_value_t nInitVal )
|
{
|
m_hSem = ::CreateSemaphore( (LPSECURITY_ATTRIBUTES)NULL, nInitVal, 1, (LPCTSTR)NULL );
|
}
|
|
COISemaphore::~COISemaphore()
|
{
|
::CloseHandle( m_hSem );
|
}
|
|
int COISemaphore::Post()
|
{
|
return (::ReleaseSemaphore( m_hSem, 1, (LPLONG)NULL ) != 0) ? 0 : -1;
|
}
|
|
int COISemaphore::Wait()
|
{
|
// return (WaitForSingleObject( m_handle, INFINITE ) == WAIT_OBJECT_0) ? 0 : -1;
|
return Wait( INFINITE );
|
}
|
|
int COISemaphore::Wait( DWORD dwTimeOutMillis )
|
{
|
return (WaitForSingleObject( m_hSem, dwTimeOutMillis ) == WAIT_OBJECT_0) ? 0 : -1;
|
}
|
|
int COISemaphore::TryWait()
|
{
|
return -1; // %! not implemented
|
}
|
|
int COISemaphore::GetValue( int &nValue )
|
{
|
return 0; // %! not implemented
|
}
|
|
int COISemaphore::WaitForMultipleObjects( DWORD dwCount, COISemaphore *lpSem[], bool bWaitAll, DWORD dwMilliSeconds )
|
{
|
DWORD dwRet;
|
OISemaphoreHandle *lpHandle = new OISemaphoreHandle[dwCount];
|
|
for ( DWORD dwIndex = 0; dwIndex < dwCount; dwIndex++ )
|
lpHandle[dwIndex] = lpSem[dwIndex]->GetHandle();
|
|
dwRet = ::WaitForMultipleObjects( dwCount, lpHandle, bWaitAll, dwMilliSeconds );
|
delete [] lpHandle;
|
if ( WAIT_TIMEOUT == dwRet )
|
return -1;
|
|
return (dwRet - WAIT_OBJECT_0);
|
}
|
|
// Linux ---------------------------------------------------------------
|
#else
|
|
COISemaphore::COISemaphore( oi_value_t nInitVal )
|
{
|
sem_init( &m_hSem, 0, nInitVal );
|
}
|
|
COISemaphore::~COISemaphore()
|
{
|
sem_destroy( &m_hSem );
|
}
|
|
int COISemaphore::Post()
|
{
|
return sem_post( &m_hSem );
|
}
|
|
int COISemaphore::Wait()
|
{
|
return sem_wait( &m_hSem );
|
}
|
|
int COISemaphore::Wait( DWORD dwTimeOutMillis )
|
{
|
struct timespec ts;
|
long nSecs;
|
long nAdd;
|
|
clock_gettime( CLOCK_REALTIME, &ts );
|
nSecs = dwTimeOutMillis / 1000;
|
dwTimeOutMillis = dwTimeOutMillis % 1000;
|
|
dwTimeOutMillis = dwTimeOutMillis * 1000 * 1000 + ts.tv_nsec;
|
nAdd = dwTimeOutMillis / (1000 * 1000 * 1000);
|
ts.tv_sec += (nAdd + nSecs);
|
ts.tv_nsec = dwTimeOutMillis % (1000 * 1000 * 1000);
|
|
return sem_timedwait( &m_hSem, &ts );
|
}
|
|
int COISemaphore::TryWait()
|
{
|
return sem_trywait( &m_hSem );
|
}
|
|
int COISemaphore::GetValue( int &nValue )
|
{
|
return sem_getvalue( &m_hSem, &nValue );
|
}
|
|
int COISemaphore::WaitForMultipleObjects( DWORD dwCount, COISemaphore *lpSem[], bool bWaitAll, DWORD dwMilliSeconds )
|
{
|
int nRet;
|
COISemaphore sem;
|
DWORD dwIndex;
|
COICriticalSection cs;
|
int nReleaseIndex = -1; // Which is first release, For WaitAll is false
|
int nReleaseCount = 0; // release count, For WaitAll is true
|
COIWaitForThread *lpThread;
|
COIWaitForThreadList listThread;
|
COIWaitForThreadList::iterator it;
|
|
// Create thread
|
for ( dwIndex = 0; dwIndex < dwCount; dwIndex++ )
|
{
|
lpThread = new COIWaitForThread( cs );
|
lpThread->m_pWaitSem = lpSem[dwIndex];
|
lpThread->m_bWaitAll = bWaitAll;
|
lpThread->m_pReleaseIndex = &nReleaseIndex;
|
lpThread->m_pReleaseCount = &nReleaseCount;
|
lpThread->m_dwIndex = dwIndex;
|
lpThread->m_dwCount = dwCount;
|
|
lpThread->m_pFinishSem = &sem;
|
listThread.push_back( lpThread );
|
lpThread->Start();
|
} // End of for ( dwIndex = 0; dwIndex < dwCount; dwIndex++ )
|
|
if ( INFINITE == dwMilliSeconds )
|
nRet = sem.Wait();
|
else
|
nRet = sem.Wait( dwMilliSeconds );
|
// Release thread
|
it = listThread.begin();
|
for ( dwIndex = 0; dwIndex < dwCount; dwIndex++ )
|
{
|
lpThread = *it;
|
|
// Release sem
|
lpSem[dwIndex]->Post();
|
// Wait for thread end
|
lpThread->Wait( 100 );
|
// delete thread
|
delete lpThread;
|
}
|
listThread.clear();
|
|
if ( 0 == nRet )
|
{
|
if ( bWaitAll )
|
return 0;
|
else
|
return nReleaseIndex;
|
}
|
|
return -1;
|
}
|
|
#endif // End of #ifdef _WIN32
|
|
} // End of namespace OIComm
|