⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 switrdmonitor.cpp

📁 openvxi3.4是一个voicexml对话脚本语言的解释器源码.可用VC6.0编译.
💻 CPP
📖 第 1 页 / 共 2 页
字号:

/****************License************************************************
 * Vocalocity OpenVXI
 * Copyright (C) 2004-2005 by Vocalocity, Inc. All Rights Reserved.
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *  
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 * Vocalocity, the Vocalocity logo, and VocalOS are trademarks or 
 * registered trademarks of Vocalocity, Inc. 
 * OpenVXI is a trademark of Scansoft, Inc. and used under license 
 * by Vocalocity.
 ***********************************************************************/

#include "SWIutilInternal.h"

#ifndef _WIN32
#include <sys/time.h>
#include <errno.h>
#define INFINITE (~0)
#endif

#include "SWItrdMonitor.hpp"
#include <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++;
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -