📄 switrdmonitor.cpp
字号:
/****************License************************************************
*
* Copyright 2000-2003. ScanSoft, Inc.
*
* Use of this software is subject to notices and obligations set forth
* in the SpeechWorks Public License - Software Version 1.2 which is
* included with this software.
*
* ScanSoft is a registered trademark of ScanSoft, Inc., and OpenSpeech,
* SpeechWorks and the SpeechWorks logo are registered trademarks or
* trademarks of SpeechWorks International, Inc. in the United States
* and other countries.
*
***********************************************************************/
#include <vxibuildopts.h>
#if P_VXI
#include "SWIutilInternal.h"
#ifndef _WIN32
#include <sys/time.h>
#include <errno.h>
#define INFINITE (~0)
#endif
#include "SWItrdMonitor.hpp"
#include <vxi/VXItrd.h>
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#else
#include <pthread.h>
#endif
// ---------- Constants ----------
const int SWItrdMonitor::SUCCESS = 0;
const int SWItrdMonitor::FAILURE = -1;
const int SWItrdMonitor::NOT_OWNER = 1;
// Static initialization for WIN32
#ifdef _WIN32
static void *createMutex(bool locked)
{
HANDLE *k = new HANDLE;
*k = CreateMutex(NULL, locked ? TRUE : FALSE, NULL);
return k;
}
static void deleteMutex(void *mutex)
{
HANDLE *k = (HANDLE *) mutex;
CloseHandle(*k);
delete k;
}
static int lockMutex(void* mutex)
{
int rc = SWItrdMonitor::SUCCESS;
switch (WaitForSingleObject(*(static_cast<HANDLE *>(mutex)), INFINITE))
{
case WAIT_FAILED:
rc = SWItrdMonitor::FAILURE;
break;
case WAIT_ABANDONED:
// should we log this?
break;
}
return rc;
}
static int unlockMutex(void* mutex)
{
return ReleaseMutex(*(static_cast<HANDLE *>(mutex))) ?
SWItrdMonitor::SUCCESS :
SWItrdMonitor::FAILURE;
}
static int waitForEvent(void *mutex,
void *event,
unsigned long millisecs,
bool *expiredF)
{
if (::unlockMutex(mutex) != SWItrdMonitor::SUCCESS)
{
return SWItrdMonitor::FAILURE;
}
int rc = SWItrdMonitor::SUCCESS;
DWORD waitrc = WaitForSingleObject(*(static_cast<HANDLE *>(event)),
millisecs);
switch (waitrc)
{
case WAIT_OBJECT_0:
if (expiredF != NULL) *expiredF = false;
break;
case WAIT_TIMEOUT:
if (expiredF != NULL) *expiredF = true;
break;
case WAIT_FAILED:
rc = SWItrdMonitor::FAILURE;
break;
case WAIT_ABANDONED:
// should we log this?
break;
}
::lockMutex(mutex);
return rc;
}
static int notifyEvent(void *event, bool broadcast)
{
SetEvent(*(static_cast<HANDLE *>(event)));
return SWItrdMonitor::SUCCESS;
}
#else
static void *createMutex(bool locked)
{
pthread_mutex_t *lock = new pthread_mutex_t;
pthread_mutex_init(lock,NULL);
if (locked) pthread_mutex_lock(lock);
return lock;
}
static void deleteMutex(void *mutex)
{
pthread_mutex_t *lock = (pthread_mutex_t *) mutex;
pthread_mutex_destroy(lock);
delete lock;
}
static int lockMutex(void *mutex)
{
return pthread_mutex_lock(static_cast<pthread_mutex_t *>(mutex)) == 0 ?
SWItrdMonitor::SUCCESS :
SWItrdMonitor::FAILURE;
}
static int unlockMutex(void *mutex)
{
return pthread_mutex_unlock(static_cast<pthread_mutex_t *>(mutex)) == 0 ?
SWItrdMonitor::SUCCESS :
SWItrdMonitor::FAILURE;
}
static int waitForEvent(void *mutex, void *event,
unsigned long millisecs,
bool *expiredF)
{
int rc = SWItrdMonitor::SUCCESS;
if (millisecs == INFINITE)
{
if (pthread_cond_wait(static_cast<pthread_cond_t *>(event),
static_cast<pthread_mutex_t *>(mutex)) != 0)
rc = SWItrdMonitor::FAILURE;
}
else
{
struct timeval now;
struct timespec timeout;
gettimeofday(&now, NULL);
timeout.tv_sec = now.tv_sec + millisecs / 1000;
unsigned long microsecs = now.tv_usec + (millisecs % 1000) * 1000;
if (microsecs >= 1000000)
{
microsecs -= 1000000;
timeout.tv_sec++;
}
timeout.tv_nsec = microsecs * 1000;
rc = pthread_cond_timedwait(static_cast<pthread_cond_t *>(event),
static_cast<pthread_mutex_t *>(mutex),
&timeout);
switch (rc)
{
case 0:
if (expiredF != NULL) *expiredF = false;
rc = SWItrdMonitor::SUCCESS;
break;
case ETIMEDOUT:
if (expiredF != NULL) *expiredF = true;
rc = SWItrdMonitor::SUCCESS;
break;
default:
rc = SWItrdMonitor::FAILURE;
}
}
return rc;
}
static int notifyEvent(void *event, bool broadcast)
{
pthread_cond_t *p = static_cast<pthread_cond_t *>(event);
int rc;
if (broadcast)
rc = pthread_cond_broadcast(p);
else
rc = pthread_cond_signal(p);
if (rc == 0)
rc = SWItrdMonitor::SUCCESS;
else
rc = SWItrdMonitor::FAILURE;
return rc;
}
#endif
void* SWItrdMonitor::_globalLock = createMutex(false);
SWItrdMonitor::HandleListItem * volatile SWItrdMonitor::_freeThreadList = NULL;
SWItrdMonitor::HandleListItem * volatile SWItrdMonitor::_freeMutexList = NULL;
// SWItrdMonitor::SWItrdMonitor
// Refer to SWItrdMonitor.hpp for doc.
SWItrdMonitor::SWItrdMonitor(Policy policy):
_ownerThread((VXIthreadID) -1),_lockCount(0),
_firstWaitingThread(NULL),_lastWaitingThread(NULL),
_mutex(NULL),
_policy(policy)
{
if (policy != POOLED)
{
_mutex = new HandleListItem;
// We don't initialize the other fields as we don't really care
_mutex->_handle = ::createMutex(false);
}
}
// SWItrdMonitor::~SWItrdMonitor
// Refer to SWItrdMonitor.hpp for doc.
SWItrdMonitor::~SWItrdMonitor()
{
::lockMutex(_globalLock);
// If the list of waiting threads is not NULL, we unlock them and put them
// back on the free list. This way, wait() will return with an error rather
// than block indefinitely.
if (_firstWaitingThread != NULL)
{
notifyAllHandles();
}
if (_policy == POOLED)
{
// release the mutex if we have one, and put it back on the free list.
if (_mutex != NULL)
{
::unlockMutex(_mutex->_handle);
_mutex->_next = _freeMutexList;
_freeMutexList = _mutex;
_mutex = NULL;
}
::unlockMutex(_globalLock);
}
else
{
::unlockMutex(_globalLock);
::deleteMutex(_mutex->_handle);
delete _mutex;
}
}
// lock
// Refer to SWItrdMonitor.hpp for doc.
int SWItrdMonitor::lock()
{
// body
VXIthreadID threadId = VXItrdThreadGetID();
if (threadId == _ownerThread)
{
_lockCount++;
return SUCCESS;
}
int rc = SUCCESS;
if (_policy == POOLED)
{
if (::lockMutex(_globalLock) != SUCCESS)
return FAILURE;
bool newMutex = false;
if (_mutex == NULL)
{
if (_freeMutexList == NULL)
{
_mutex = new HandleListItem;
// We don't initialize the other fields as we don't really care
_mutex->_handle = ::createMutex(true);
newMutex = true;
if (_mutex->_handle == NULL)
{
delete _mutex;
_mutex = NULL;
}
}
else
{
// Take a mutex from the free list. This actually is a stack of mutex
// as it is. I don't think it causes a problem anyway.
_mutex = _freeMutexList;
_freeMutexList = _freeMutexList->_next;
}
_mutex->_count = 1;
}
else
{
_mutex->_count++;
}
rc = ::unlockMutex(_globalLock);
if (rc != SUCCESS || _mutex == NULL)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -