SWItrdMonitor.cpp
上传用户:xqtpzdz
上传日期:2022-05-21
资源大小:1764k
文件大小:15k
源码类别:

xml/soap/webservice

开发平台:

Visual C++

  1. /****************License************************************************
  2.  * Vocalocity OpenVXI
  3.  * Copyright (C) 2004-2005 by Vocalocity, Inc. All Rights Reserved.
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  *  
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  * Vocalocity, the Vocalocity logo, and VocalOS are trademarks or 
  18.  * registered trademarks of Vocalocity, Inc. 
  19.  * OpenVXI is a trademark of Scansoft, Inc. and used under license 
  20.  * by Vocalocity.
  21.  ***********************************************************************/
  22. #include "SWIutilInternal.h"
  23. #ifndef _WIN32
  24. #include <sys/time.h>
  25. #include <errno.h>
  26. #define INFINITE (~0)
  27. #endif
  28. #include "SWItrdMonitor.hpp"
  29. #include <VXItrd.h>
  30. #ifdef _WIN32
  31. #ifndef WIN32_LEAN_AND_MEAN
  32. #define WIN32_LEAN_AND_MEAN
  33. #endif
  34. #include <windows.h>
  35. #else
  36. #include <pthread.h>
  37. #endif
  38. // ---------- Constants ----------
  39. const int SWItrdMonitor::SUCCESS = 0;
  40. const int SWItrdMonitor::FAILURE = -1;
  41. const int SWItrdMonitor::NOT_OWNER = 1;
  42. // Static initialization for WIN32
  43. #ifdef _WIN32
  44. static void *createMutex(bool locked)
  45. {
  46.   HANDLE *k = new HANDLE;
  47.   *k = CreateMutex(NULL, locked ? TRUE : FALSE, NULL);
  48.   return k;
  49. }
  50. static void deleteMutex(void *mutex)
  51. {
  52.   HANDLE *k = (HANDLE *) mutex;
  53.   CloseHandle(*k);
  54.   delete k;
  55. }
  56. static int lockMutex(void* mutex)
  57. {
  58.   int rc = SWItrdMonitor::SUCCESS;
  59.   switch (WaitForSingleObject(*(static_cast<HANDLE *>(mutex)), INFINITE))
  60.   {
  61.    case WAIT_FAILED:
  62.      rc = SWItrdMonitor::FAILURE;
  63.      break;
  64.    case WAIT_ABANDONED:
  65.      // should we log this?
  66.      break;
  67.   }
  68.   return rc;
  69. }
  70. static int unlockMutex(void* mutex)
  71. {
  72.   return ReleaseMutex(*(static_cast<HANDLE *>(mutex))) ?
  73.     SWItrdMonitor::SUCCESS :
  74.     SWItrdMonitor::FAILURE;
  75. }
  76. static int waitForEvent(void *mutex,
  77.                         void *event,
  78.                         unsigned long millisecs,
  79.                         bool *expiredF)
  80. {
  81.   if (::unlockMutex(mutex) != SWItrdMonitor::SUCCESS)
  82.   {
  83.     return SWItrdMonitor::FAILURE;
  84.   }
  85.   int rc = SWItrdMonitor::SUCCESS;
  86.   DWORD waitrc = WaitForSingleObject(*(static_cast<HANDLE *>(event)),
  87.                                      millisecs);
  88.   switch (waitrc)
  89.   {
  90.    case WAIT_OBJECT_0:
  91.      if (expiredF != NULL) *expiredF = false;
  92.      break;
  93.    case WAIT_TIMEOUT:
  94.      if (expiredF != NULL) *expiredF = true;
  95.      break;
  96.    case WAIT_FAILED:
  97.      rc = SWItrdMonitor::FAILURE;
  98.      break;
  99.    case WAIT_ABANDONED:
  100.      // should we log this?
  101.      break;
  102.   }
  103.   ::lockMutex(mutex);
  104.   return rc;
  105. }
  106. static int notifyEvent(void *event, bool broadcast)
  107. {
  108.   SetEvent(*(static_cast<HANDLE *>(event)));
  109.   return SWItrdMonitor::SUCCESS;
  110. }
  111. #else
  112. static void *createMutex(bool locked)
  113. {
  114.   pthread_mutex_t *lock = new pthread_mutex_t;
  115.   pthread_mutex_init(lock,NULL);
  116.   if (locked) pthread_mutex_lock(lock);
  117.   return lock;
  118. }
  119. static void deleteMutex(void *mutex)
  120. {
  121.   pthread_mutex_t *lock = (pthread_mutex_t *) mutex;
  122.   pthread_mutex_destroy(lock);
  123.   delete lock;
  124. }
  125. static int lockMutex(void *mutex)
  126. {
  127.   return pthread_mutex_lock(static_cast<pthread_mutex_t *>(mutex)) == 0 ?
  128.     SWItrdMonitor::SUCCESS :
  129.     SWItrdMonitor::FAILURE;
  130. }
  131. static int unlockMutex(void *mutex)
  132. {
  133.   return pthread_mutex_unlock(static_cast<pthread_mutex_t *>(mutex)) == 0 ?
  134.     SWItrdMonitor::SUCCESS :
  135.     SWItrdMonitor::FAILURE;
  136. }
  137. static int waitForEvent(void *mutex, void *event,
  138.                         unsigned long millisecs,
  139.                         bool *expiredF)
  140. {
  141.   int rc = SWItrdMonitor::SUCCESS;
  142.   if (millisecs == INFINITE)
  143.   {
  144.     if (pthread_cond_wait(static_cast<pthread_cond_t *>(event),
  145.                           static_cast<pthread_mutex_t *>(mutex)) != 0)
  146.       rc = SWItrdMonitor::FAILURE;
  147.   }
  148.   else
  149.   {
  150.     struct timeval now;
  151.     struct timespec timeout;
  152.     gettimeofday(&now, NULL);
  153.     timeout.tv_sec = now.tv_sec + millisecs / 1000;
  154.     unsigned long microsecs = now.tv_usec + (millisecs % 1000) * 1000;
  155.     if (microsecs >= 1000000)
  156.     {
  157.       microsecs -= 1000000;
  158.       timeout.tv_sec++;
  159.     }
  160.     timeout.tv_nsec = microsecs * 1000;
  161.     rc = pthread_cond_timedwait(static_cast<pthread_cond_t *>(event),
  162.                                 static_cast<pthread_mutex_t *>(mutex),
  163.                                 &timeout);
  164.     switch (rc)
  165.     {
  166.      case 0:
  167.        if (expiredF != NULL) *expiredF = false;
  168.        rc = SWItrdMonitor::SUCCESS;
  169.        break;
  170.      case ETIMEDOUT:
  171.        if (expiredF != NULL) *expiredF = true;
  172.        rc = SWItrdMonitor::SUCCESS;
  173.        break;
  174.      default:
  175.        rc = SWItrdMonitor::FAILURE;
  176.     }
  177.   }
  178.   return rc;
  179. }
  180. static int notifyEvent(void *event, bool broadcast)
  181. {
  182.   pthread_cond_t *p = static_cast<pthread_cond_t *>(event);
  183.   int rc;
  184.   if (broadcast)
  185.     rc = pthread_cond_broadcast(p);
  186.   else
  187.     rc = pthread_cond_signal(p);
  188.   if (rc == 0)
  189.     rc = SWItrdMonitor::SUCCESS;
  190.   else
  191.     rc = SWItrdMonitor::FAILURE;
  192.   return rc;
  193. }
  194. #endif
  195. void* SWItrdMonitor::_globalLock = createMutex(false);
  196. SWItrdMonitor::HandleListItem * volatile SWItrdMonitor::_freeThreadList = NULL;
  197. SWItrdMonitor::HandleListItem * volatile SWItrdMonitor::_freeMutexList = NULL;
  198. // SWItrdMonitor::SWItrdMonitor
  199. // Refer to SWItrdMonitor.hpp for doc.
  200. SWItrdMonitor::SWItrdMonitor(Policy policy):
  201.   _ownerThread((VXIthreadID) -1),_lockCount(0),
  202.   _firstWaitingThread(NULL),_lastWaitingThread(NULL),
  203.   _mutex(NULL),
  204.   _policy(policy)
  205. {
  206.   if (policy != POOLED)
  207.   {
  208.     _mutex = new HandleListItem;
  209.     // We don't initialize the other fields as we don't really care
  210.     _mutex->_handle = ::createMutex(false);
  211.   }
  212. }
  213. // SWItrdMonitor::~SWItrdMonitor
  214. // Refer to SWItrdMonitor.hpp for doc.
  215. SWItrdMonitor::~SWItrdMonitor()
  216. {
  217.   ::lockMutex(_globalLock);
  218.   // If the list of waiting threads is not NULL, we unlock them and put them
  219.   // back on the free list.  This way, wait() will return with an error rather
  220.   // than block indefinitely.
  221.   if (_firstWaitingThread != NULL)
  222.   {
  223.     notifyAllHandles();
  224.   }
  225.   if (_policy == POOLED)
  226.   {
  227.     // release the mutex if we have one, and put it back on the free list.
  228.     if (_mutex != NULL)
  229.     {
  230.       ::unlockMutex(_mutex->_handle);
  231.       _mutex->_next = _freeMutexList;
  232.       _freeMutexList = _mutex;
  233.       _mutex = NULL;
  234.     }
  235.     ::unlockMutex(_globalLock);
  236.   }
  237.   else
  238.   {
  239.     ::unlockMutex(_globalLock);
  240.     ::deleteMutex(_mutex->_handle);
  241.     delete _mutex;
  242.   }
  243. }
  244. // lock
  245. // Refer to SWItrdMonitor.hpp for doc.
  246. int SWItrdMonitor::lock()
  247. {
  248.   // body
  249.   VXIthreadID threadId = VXItrdThreadGetID();
  250.   if (threadId == _ownerThread)
  251.   {
  252.     _lockCount++;
  253.     return SUCCESS;
  254.   }
  255.   int rc = SUCCESS;
  256.   if (_policy == POOLED)
  257.   {
  258.     if (::lockMutex(_globalLock) != SUCCESS)
  259.       return FAILURE;
  260.     bool newMutex = false;
  261.     if (_mutex == NULL)
  262.     {
  263.       if (_freeMutexList == NULL)
  264.       {
  265.         _mutex = new HandleListItem;
  266.         // We don't initialize the other fields as we don't really care
  267.         _mutex->_handle = ::createMutex(true);
  268.         newMutex = true;
  269.         if (_mutex->_handle == NULL)
  270.         {
  271.           delete _mutex;
  272.           _mutex = NULL;
  273.         }
  274.       }
  275.       else
  276.       {
  277.         // Take a mutex from the free list.  This actually is a stack of mutex
  278.         // as it is.  I don't think it causes a problem anyway.
  279.         _mutex = _freeMutexList;
  280.         _freeMutexList = _freeMutexList->_next;
  281.       }
  282.       _mutex->_count = 1;
  283.     }
  284.     else
  285.     {
  286.       _mutex->_count++;
  287.     }
  288.     rc = ::unlockMutex(_globalLock);
  289.     if (rc != SUCCESS || _mutex == NULL)
  290.     {
  291.       return FAILURE;
  292.     }
  293.     if (!newMutex)
  294.     {
  295.       rc = ::lockMutex(_mutex->_handle);
  296.     }
  297.   }
  298.   else
  299.   {
  300.     rc = ::lockMutex(_mutex->_handle);
  301.   }
  302.   if (rc == SUCCESS)
  303.   {
  304.     _ownerThread = threadId;
  305.     _lockCount = 1;
  306.   }
  307.   return rc;
  308. }
  309. // unlock
  310. // Refer to SWItrdMonitor.hpp for doc.
  311. int SWItrdMonitor::unlock()
  312. {
  313.   VXIthreadID threadId = VXItrdThreadGetID();
  314.   if (threadId != _ownerThread)
  315.   {
  316.     return NOT_OWNER;
  317.   }
  318.   int rc = SUCCESS;
  319.   if (_policy == POOLED)
  320.   {
  321.     ::lockMutex(_globalLock);
  322.     if (--_lockCount == 0)
  323.     {
  324.       _ownerThread = (VXIthreadID) -1;
  325.       rc = ::unlockMutex(_mutex->_handle);
  326.       if (--_mutex->_count == 0)
  327.       {
  328.         _mutex->_next = _freeMutexList;
  329.         _freeMutexList = _mutex;
  330.         _mutex = NULL;
  331.       }
  332.     }
  333.     ::unlockMutex(_globalLock);
  334.   }
  335.   else
  336.   {
  337.     if (--_lockCount == 0)
  338.     {
  339.       _ownerThread = (VXIthreadID) -1;
  340.       rc = ::unlockMutex(_mutex->_handle);
  341.     }
  342.   }
  343.   return rc;
  344. }
  345. // wait
  346. // Refer to SWItrdMonitor.hpp for doc.
  347. int SWItrdMonitor::wait()
  348. {
  349.   return wait(INFINITE,NULL);
  350. }
  351. // wait
  352. // Refer to SWItrdMonitor.hpp for doc.
  353. int SWItrdMonitor::wait(unsigned long millisecs, bool *expiredF)
  354. {
  355.   // body
  356.   VXIthreadID threadId = VXItrdThreadGetID();
  357.   if (threadId != _ownerThread)
  358.   {
  359.     return NOT_OWNER;
  360.   }
  361.   int count = _lockCount;
  362.   _ownerThread = (VXIthreadID) -1;
  363.   _lockCount = 0;
  364.   HandleListItem *listItem = getHandle();
  365.   int rc = waitForEvent(_mutex->_handle, listItem->_handle,
  366.                         millisecs, expiredF);
  367.   resetHandle(listItem);
  368.   if (rc == SUCCESS)
  369.   {
  370.     _ownerThread = threadId;
  371.     _lockCount = count;
  372.   }
  373.   return rc;
  374. }
  375. // notify
  376. // Refer to SWItrdMonitor.hpp for doc.
  377. int SWItrdMonitor::notify()
  378. {
  379.   // body
  380.   VXIthreadID threadId = VXItrdThreadGetID();
  381.   if (threadId != _ownerThread)
  382.   {
  383.     return NOT_OWNER;
  384.   }
  385.   int rc = SUCCESS;
  386.   ::lockMutex(_globalLock);
  387.   if (_firstWaitingThread != NULL)
  388.   {
  389. #ifdef _WIN32
  390.     rc = ::notifyEvent(_firstWaitingThread->_handle, false);
  391.     // Remove the handle from the waiting threads list.
  392.     HandleListItem *tmp = _firstWaitingThread;
  393.     _firstWaitingThread = _firstWaitingThread->_next;
  394.     tmp->_next = NULL;
  395.     if (_firstWaitingThread == NULL)
  396.       _lastWaitingThread = NULL;
  397.     else
  398.       _firstWaitingThread->_prev = NULL;
  399. #else
  400.   rc = ::notifyEvent(_firstWaitingThread->_handle, false);
  401. #endif
  402.   }
  403.   ::unlockMutex(_globalLock);
  404.   return rc;
  405. }
  406. // notifyAll
  407. // Refer to SWItrdMonitor.hpp for doc.
  408. int SWItrdMonitor::notifyAll()
  409. {
  410.   // body
  411.   VXIthreadID threadId = VXItrdThreadGetID();
  412.   if (threadId != _ownerThread)
  413.   {
  414.     return NOT_OWNER;
  415.   }
  416.   ::lockMutex(_globalLock);
  417.   int rc = notifyAllHandles();
  418.   ::unlockMutex(_globalLock);
  419.   return rc;
  420. }
  421. int SWItrdMonitor::notifyAllHandles()
  422. {
  423.   int rc = SUCCESS;
  424. #ifdef _WIN32
  425.   while (_firstWaitingThread != NULL)
  426.   {
  427.     HandleListItem *tmp = _firstWaitingThread;
  428.     _firstWaitingThread = _firstWaitingThread->_next;
  429.     tmp->_next = tmp->_prev = NULL;
  430.     if (notifyEvent(tmp->_handle, true) != SUCCESS)
  431.       rc = FAILURE;
  432.   }
  433.   _lastWaitingThread = NULL;
  434. #else
  435.   if (_firstWaitingThread != NULL)
  436.   {
  437.     rc = notifyEvent(_firstWaitingThread->_handle, true);
  438.   }
  439. #endif
  440.   return rc;
  441. }
  442. #ifdef _WIN32
  443. SWItrdMonitor::HandleListItem *SWItrdMonitor::getHandle()
  444. {
  445.   HandleListItem *handle = NULL;
  446.   ::lockMutex(_globalLock);
  447.   if (_freeThreadList == NULL)
  448.   {
  449.     handle = new HandleListItem;
  450.     // No need to initialize _owner, _next and _prev at this point.  They are
  451.     // initialized below.
  452.     HANDLE *k = new HANDLE;
  453.     *k = CreateEvent(NULL, FALSE, FALSE, NULL);
  454.     handle->_handle = k;
  455.   }
  456.   else
  457.   {
  458.     // Take the first NT event in the free list and make sure it is reset
  459.     // Altough it should be.
  460.     handle = _freeThreadList;
  461.     _freeThreadList = handle->_next;
  462.     ResetEvent(*(static_cast<HANDLE *>(handle->_handle)));
  463.   }
  464.   // Insert in list of pending notifications.
  465.   if (_lastWaitingThread == NULL)
  466.   {
  467.     // empty list.
  468.     _lastWaitingThread = _firstWaitingThread = handle;
  469.     handle->_prev = handle->_next = NULL;
  470.   }
  471.   else
  472.   {
  473.     // add to the end of the list
  474.     _lastWaitingThread->_next = handle;
  475.     handle->_prev = _lastWaitingThread;
  476.     handle->_next = NULL;
  477.     _lastWaitingThread = handle;
  478.   }
  479.   ::unlockMutex(_globalLock);
  480.   return handle;
  481. }
  482. void SWItrdMonitor::resetHandle(HandleListItem *handle)
  483. {
  484.   ::lockMutex(_globalLock);
  485.   ResetEvent(*(static_cast<HANDLE *>(handle->_handle)));
  486.   // Remove from the pending list.
  487.   if (handle == _firstWaitingThread)
  488.   {
  489.     // The handle is the first one on the pending list.
  490.     _firstWaitingThread = handle->_next;
  491.     if (handle == _lastWaitingThread) _lastWaitingThread = NULL;
  492.   }
  493.   else if (handle == _lastWaitingThread)
  494.   {
  495.     // The handle is the last one on the pending list, but not the first.
  496.     _lastWaitingThread = handle->_prev;
  497.     _lastWaitingThread->_next = NULL;
  498.   }
  499.   else if (handle->_prev != NULL && handle->_next != NULL)
  500.   {
  501.     // The handle is neither the first one, nor the last one.
  502.     handle->_prev->_next = handle->_next;
  503.     handle->_next->_prev = handle->_prev;
  504.   }
  505.   // Now put back in the free list
  506.   handle->_next = _freeThreadList;
  507.   handle->_prev = NULL;
  508.   _freeThreadList = handle;
  509.   ::unlockMutex(_globalLock);
  510. }
  511. #else
  512. SWItrdMonitor::HandleListItem *SWItrdMonitor::getHandle()
  513. {
  514.   HandleListItem *handle = NULL;
  515.   ::lockMutex(_globalLock);
  516.   if (_firstWaitingThread != NULL)
  517.   {
  518.     handle = _firstWaitingThread;
  519.     handle->_count++;
  520.   }
  521.   else
  522.   {
  523.     if (_freeThreadList == NULL)
  524.     {
  525.       handle = new HandleListItem;
  526.       // No need to initialize _owner, _next and _prev at this point.  They are
  527.       // initialized below.
  528.       pthread_cond_t *p = new pthread_cond_t;
  529.       pthread_cond_init(p, NULL);
  530.       handle->_handle = p;
  531.     }
  532.     else
  533.     {
  534.       // Take the first event in the free list.
  535.       // Altough it should be.
  536.       handle = _freeThreadList;
  537.       _freeThreadList = handle->_next;
  538.     }
  539.     _lastWaitingThread = _firstWaitingThread = handle;
  540.     handle->_prev = handle->_next = NULL;
  541.     handle->_count = 1;
  542.   }
  543.   ::unlockMutex(_globalLock);
  544.   return handle;
  545. }
  546. void SWItrdMonitor::resetHandle(HandleListItem *handle)
  547. {
  548.   ::lockMutex(_globalLock);
  549.   // Remove from the pending list if not already removed.
  550.   if (--handle->_count == 0)
  551.   {
  552.     _firstWaitingThread = _lastWaitingThread = NULL;
  553.     // Now put back in the free list
  554.     handle->_next = _freeThreadList;
  555.     handle->_prev = NULL;
  556.     _freeThreadList = handle;
  557.   }
  558.   ::unlockMutex(_globalLock);
  559. }
  560. #endif // _WIN32