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

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. /*****************************************************************************
  23.  *****************************************************************************
  24.  *
  25.  * SBtrd API implementation
  26.  *
  27.  * This provides the Win32 implementation of the VXItrd API for basic
  28.  * thread operations and locks. Unlike most of the other VXI APIs,
  29.  * this is implemented in a library (on Windows a DLL with a specific
  30.  * name, on other operating systems as a static, shared, or dynamic
  31.  * library). Implementations of this API are operating system
  32.  * dependant.
  33.  *
  34.  * To avoid cyclic dependancies, this does not perform logging. Clients
  35.  * must do error logging themselves based on passed return codes.
  36.  *
  37.  *****************************************************************************
  38.  *****************************************************************************/
  39. // -----1=0-------2=0-------3=0-------4=0-------5=0-------6=0-------7=0-------8
  40. #ifndef WIN32
  41. #error This file is intended only for use with the Microsoft Windows API.
  42. #endif
  43. #include <stdlib.h>
  44. #define WIN32_LEAN_AND_MEAN
  45. #include <windows.h>
  46. #include <process.h>
  47. #define VXITRD_EXPORTS
  48. #include "VXItrd.h"                   // Header for this API
  49. #if ( ! defined(NDEBUG) ) && ( ! defined(VXITRD_RECURSIVE_MUTEX) )
  50. #include <assert.h>
  51. /* Suppress/disable warnings triggered by asserts below */
  52. #pragma warning(4 : 4130) /* logical operation on address of string constant */
  53. #endif
  54. extern "C" struct VXItrdMutex {
  55. #ifdef VXITRD_KERNEL_MUTEX
  56.   HANDLE mutex;
  57. #else
  58.   CRITICAL_SECTION critSection;
  59. #endif
  60. #if ( ! defined(NDEBUG) ) && ( ! defined(VXITRD_RECURSIVE_MUTEX) )
  61.   volatile bool locked;
  62. #endif
  63. };
  64. extern "C" struct VXItrdThread {
  65.   HANDLE threadHandle;
  66.   unsigned int threadID;
  67. };
  68. extern "C" struct VXItrdTimer {
  69.   HANDLE timerEvent;
  70. };
  71. static VXIint32 g_threadStackSize = 0;
  72. // -----1=0-------2=0-------3=0-------4=0-------5=0-------6=0-------7=0-------8
  73. /**
  74.  * Creates a new mutex initialized to the unlocked state.  If the calling
  75.  * thread terminates, the created mutex is not automatically deallocated as
  76.  * it may be shared among multiple threads.
  77.  *
  78.  * @return Fatal error (ex: system lacks necessary resources for creation)
  79.  *         Success; valid mutex has been created
  80.  */
  81. VXITRD_API VXItrdResult VXItrdMutexCreate(VXItrdMutex **mutex)
  82. {
  83.   VXItrdResult rc = VXItrd_RESULT_SUCCESS;
  84.   if (mutex == NULL) return VXItrd_RESULT_INVALID_ARGUMENT;
  85.   *mutex = NULL;
  86.   
  87.   // Create the wrapper object
  88.   VXItrdMutex *result = new VXItrdMutex;
  89.   if (result == NULL)
  90.     return VXItrd_RESULT_OUT_OF_MEMORY;
  91. #if ( ! defined(NDEBUG) ) && ( ! defined(VXITRD_RECURSIVE_MUTEX) )
  92.   result->locked = false;
  93. #endif
  94.   // Create the critical section or mutex, use Win32 exception
  95.   // handling to catch predicatable problems
  96.   __try {
  97. #ifdef VXITRD_KERNEL_MUTEX
  98.     result->mutex = CreateMutex(NULL, FALSE, NULL);
  99.     if (result->mutex == NULL)
  100.       rc = VXItrd_RESULT_SYSTEM_ERROR;
  101. #else
  102.     InitializeCriticalSection(&result->critSection);
  103. #endif
  104.   }
  105.   __except (GetExceptionCode() == STATUS_NO_MEMORY ? 
  106.     EXCEPTION_EXECUTE_HANDLER : 
  107.     EXCEPTION_CONTINUE_SEARCH ) {
  108.     rc = VXItrd_RESULT_OUT_OF_MEMORY;
  109.   }
  110.   if (rc == VXItrd_RESULT_SUCCESS)
  111.     *mutex = result;
  112.   else if (result)
  113.     delete result;
  114.   return rc;
  115. }
  116. /**
  117.  * Deletes an existing mutex.  It is illegal to delete a locked mutex.
  118.  *
  119.  * @return Fatal error (ex: invalid mutex)
  120.  *         Success; mutex has been destroyed
  121.  *         Mutex is locked
  122.  */
  123. VXITRD_API VXItrdResult VXItrdMutexDestroy(VXItrdMutex **mutex)
  124. {
  125.   VXItrdResult rc = VXItrd_RESULT_SUCCESS;
  126.   if ((! mutex) || (! *mutex)) return VXItrd_RESULT_INVALID_ARGUMENT;
  127. #if ( ! defined(NDEBUG) ) && ( ! defined(VXITRD_RECURSIVE_MUTEX) )
  128.   // Check the lock state
  129.   if ( (*mutex)->locked ) {
  130.     assert ("VXItrdMutexDestroy( ) on locked mutex" == NULL);
  131.     return VXItrd_RESULT_FATAL_ERROR;
  132.   }
  133. #endif
  134.   // Are no predictable problems, so no Win32 exception handling
  135. #ifdef VXITRD_KERNEL_MUTEX
  136.   if (CloseHandle((*mutex)->mutex) == FALSE)
  137.     rc = VXItrd_RESULT_SYSTEM_ERROR;
  138. #else
  139.   DeleteCriticalSection(&(*mutex)->critSection);
  140. #endif
  141.   delete *mutex;
  142.   *mutex = NULL;
  143.   return rc;
  144. }
  145. /**
  146.  * Locks an existing mutex.  If the mutex is already locked, the thread waits
  147.  * for the mutex to become available.
  148.  *
  149.  * @return: Fatal error (ex: invalid mutex or deadlock detected)
  150.  *          Success; mutex is now locked
  151.  *          Mutex already locked by current thread.
  152.  */
  153. VXITRD_API VXItrdResult VXItrdMutexLock(VXItrdMutex *mutex)
  154. {
  155.   if (mutex == NULL) return VXItrd_RESULT_INVALID_ARGUMENT;
  156.   
  157.   __try {
  158. #ifdef VXITRD_KERNEL_MUTEX
  159.     int result = WaitForSingleObject(mutex->mutex, INFINITE);
  160.     if (result == WAIT_FAILED) 
  161.       return VXItrd_RESULT_SYSTEM_ERROR;
  162. #else
  163.     EnterCriticalSection(&mutex->critSection);
  164. #endif
  165.   }
  166.   __except (GetExceptionCode() == STATUS_INVALID_HANDLE ? 
  167.     EXCEPTION_EXECUTE_HANDLER : 
  168.     EXCEPTION_CONTINUE_SEARCH ) {
  169.     // Yes, Microsoft says STATUS_INVALID_HANDLE is returned on low memory
  170.     return VXItrd_RESULT_OUT_OF_MEMORY;
  171.   }
  172.   
  173. #if ( ! defined(NDEBUG) ) && ( ! defined(VXITRD_RECURSIVE_MUTEX) )
  174.   // Check the lock state
  175.   if ( mutex->locked ) {
  176.     // Should not be locking the same mutex twice, very OS dependant
  177.     // (Win32 says the behavior is undefined) and not gauranteed by 
  178.     // VXItrdMutex
  179.     assert ("VXItrdMutexLock( ) on already locked mutex" == NULL);
  180.     return VXItrd_RESULT_FATAL_ERROR;
  181.   } else {
  182.     mutex->locked = true;
  183.   }
  184. #endif
  185.   return VXItrd_RESULT_SUCCESS;
  186. }
  187. /**
  188.  * Unlocks a mutex owned by the thread.
  189.  *
  190.  * @return: Fatal error (ex: invalid mutex)
  191.  *          Success; mutex no longer owned by calling thread
  192.  *          Mutex not owned by thread.
  193.  */
  194. VXITRD_API VXItrdResult VXItrdMutexUnlock(VXItrdMutex *mutex)
  195. {
  196.   if (mutex == NULL) return VXItrd_RESULT_INVALID_ARGUMENT;
  197. #if ( ! defined(NDEBUG) ) && ( ! defined(VXITRD_RECURSIVE_MUTEX) )
  198.   // Check the lock state
  199.   if ( ! mutex->locked ) {
  200.     // Unlocking a mutex that wasn't locked
  201.     assert ("VXItrdMutexUnlock( ) on unlocked mutex" == NULL);
  202.     return VXItrd_RESULT_FATAL_ERROR;
  203.   } else {
  204.     mutex->locked = false;
  205.   }
  206. #endif
  207. #ifdef VXITRD_KERNEL_MUTEX
  208.   int result = ReleaseMutex(mutex->mutex);
  209.   if (result == FALSE)
  210.     return VXItrd_RESULT_FATAL_ERROR;
  211. #else
  212.   LeaveCriticalSection(&mutex->critSection);
  213. #endif
  214.   return VXItrd_RESULT_SUCCESS;
  215. }
  216. /**
  217.  * Purpose  Create a thread.  Note thread values are not supported on OS/2.
  218.  *          execution starts on the thread immediately. To pause execution 
  219.  *          use a Mutex between the thread and the thread creator.
  220.  *
  221.  * @param   thread the thread object to be created
  222.  * @param   start_func the function for the thread to start execution on
  223.  * @param   arg the arguments to the thread function
  224.  * @return  VXItrdResult of operation.  Return SUCCESS if thread has been 
  225.  *          created and started.
  226.  *
  227.  */
  228. VXITRD_API 
  229. VXItrdResult VXItrdThreadCreate(VXItrdThread **thread,
  230. VXItrdThreadStartFunc thread_function,
  231. VXItrdThreadArg thread_arg)
  232. {
  233.   if ((thread == NULL) || (thread_function == NULL))
  234.     return VXItrd_RESULT_INVALID_ARGUMENT;
  235.   *thread = NULL;
  236.   // Create the wrapper object
  237.   VXItrdThread *result = new VXItrdThread;
  238.   if (result == NULL)
  239.     return VXItrd_RESULT_OUT_OF_MEMORY;
  240.   // Use _beginthreadex( ) so that the CRT (common runtime
  241.   // environment) is fully initialized so all CRT functions work,
  242.   // CreateThread( ) doesn't do this. However, this is Microsoft Visual C++
  243.   // specific, not part of the official Win32 API.
  244.   typedef unsigned int (__stdcall *beginthreadfunc)(void *);
  245.   beginthreadfunc func = reinterpret_cast<beginthreadfunc>(thread_function);
  246.   void *arg = static_cast<void *>(thread_arg);
  247.   result->threadHandle = 
  248.     reinterpret_cast<HANDLE>(_beginthreadex(NULL, g_threadStackSize, 
  249.                              func, arg, 0, &result->threadID));
  250.   if (result->threadHandle == 0) {
  251.     delete result;
  252.     return VXItrd_RESULT_FATAL_ERROR;
  253.   }
  254.   *thread = result;
  255.   return VXItrd_RESULT_SUCCESS;
  256. }
  257. /**
  258.  * Destroy a thread handle
  259.  *
  260.  * Note: this does NOT stop or destroy the thread, it just releases
  261.  * the handle for accessing it. If this is not done, a memory leak
  262.  * occurs, so if the creator of the thread never needs to communicate
  263.  * with the thread again it should call this immediately after the
  264.  * create if the create was successful.
  265.  *
  266.  * @param  thread  Handle to the thread to destroy
  267.  *
  268.  * @result VXItrdResult 0 on success 
  269.  */
  270. VXITRD_API VXItrdResult VXItrdThreadDestroyHandle(VXItrdThread **thread)
  271. {
  272.   if ((! thread) || (! *thread)) return VXItrd_RESULT_INVALID_ARGUMENT;
  273.   CloseHandle ((*thread)->threadHandle);
  274.   delete *thread;
  275.   *thread = NULL;
  276.   return VXItrd_RESULT_SUCCESS;
  277. }
  278. /**
  279.  * Purpose Terminate a thread.  Called by the thread on exit.
  280.  *
  281.  * @param  status  Exit code for the thread
  282.  * @result           N/A, never returns
  283.  */
  284. VXITRD_API void VXItrdThreadExit(VXItrdThreadArg status)
  285. {
  286.   _endthreadex(reinterpret_cast<unsigned int>(status));
  287. }
  288. /**
  289.  * Causes the calling thread to wait for the termination of a specified
  290.  *   'thread' with a specified timeout, in milliseconds. 
  291.  *
  292.  * @param   thread the 'thread' that is waited for its termination.
  293.  * @param   status contains the exit value of the thread's start routine.
  294.  * @return  VXItrdResult of operation.  Return SUCCESS if specified 'thread' 
  295.  *          terminating.
  296.  */
  297. VXITRD_API VXItrdResult VXItrdThreadJoin(VXItrdThread *thread,
  298.  VXItrdThreadArg *status,
  299.  long timeout)
  300. {
  301.   if ((thread == NULL ) || (status == NULL) || (timeout < -1))
  302.     return VXItrd_RESULT_INVALID_ARGUMENT;
  303.   if (timeout == -1)
  304.     timeout = INFINITE;
  305.   VXItrdResult rc;
  306.   switch (WaitForSingleObject(thread->threadHandle, timeout)) {
  307.   case WAIT_OBJECT_0:
  308.   case WAIT_ABANDONED:
  309.     rc = VXItrd_RESULT_SUCCESS;
  310.     break;
  311.   case WAIT_TIMEOUT:
  312.     rc = VXItrd_RESULT_FAILURE;
  313.     break;
  314.   default:
  315.     rc = VXItrd_RESULT_FATAL_ERROR;
  316.   }
  317.   DWORD stat;
  318.   if (rc == VXItrd_RESULT_SUCCESS) {
  319.     if (GetExitCodeThread(thread->threadHandle, &stat) == 0)
  320.       rc = VXItrd_RESULT_FATAL_ERROR;
  321.     else
  322.       *status = reinterpret_cast<VXItrdThreadArg>(stat);
  323.   }
  324.   return rc;
  325. }
  326. /**
  327.  * Get the thread ID for the specified thread
  328.  *
  329.  * @param  thread   Handle to the thread to get the ID for
  330.  *
  331.  * @result   Thread ID number
  332.  */
  333. VXITRD_API VXIthreadID VXItrdThreadGetIDFromHandle(VXItrdThread *thread)
  334. {
  335.   if (thread == NULL) 
  336.     return (VXIthreadID) -1;
  337.   return thread->threadID;
  338. }
  339. /**
  340.  * Purpose Get the ID of the current handle.
  341.  *
  342.  * @return  The current thread handle identifier.
  343.  *
  344.  */
  345. VXITRD_API VXIthreadID VXItrdThreadGetID(void)
  346. {
  347.   return GetCurrentThreadId();
  348. }
  349. /**
  350.  * Purpose Yield the process schedule in the current thread.
  351.  *
  352.  * @return  void
  353.  *
  354.  */
  355. VXITRD_API void VXItrdThreadYield(void)
  356. {
  357.   Sleep(0);
  358. }
  359. /**
  360.  * Purpose  Create a timer
  361.  *
  362.  * @param   mutex  a pointer to a mutex
  363.  * @return  VXItrdResult of operation.  Return SUCCESS if timer has been 
  364.  *          created
  365.  *
  366.  */
  367. VXITRD_API VXItrdResult VXItrdTimerCreate(VXItrdTimer **timer)
  368. {
  369.   if (timer == NULL) return VXItrd_RESULT_INVALID_ARGUMENT;
  370.   
  371.   *timer = NULL;
  372.   
  373.   // Create the wrapper object
  374.   VXItrdTimer *result = new VXItrdTimer;
  375.   if (result == NULL)
  376.     return VXItrd_RESULT_OUT_OF_MEMORY;
  377.   // Create the timer, a Win32 event
  378.   result->timerEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  379.   if (result->timerEvent == NULL) {
  380.     delete result;
  381.     return VXItrd_RESULT_FATAL_ERROR;
  382.   }
  383.   *timer = result;
  384.   return VXItrd_RESULT_SUCCESS;
  385. }
  386. /**
  387.  * Purpose  Destroy a timer
  388.  *
  389.  * @param   timer  a pointer to a timer
  390.  * @return  VXItrdResult of operation.  Return SUCCESS if timer has been 
  391.  *          created
  392.  *
  393.  */
  394. VXITRD_API VXItrdResult VXItrdTimerDestroy(VXItrdTimer **timer)
  395. {
  396.   if ((! timer) || (! *timer)) return VXItrd_RESULT_INVALID_ARGUMENT;
  397.   if (CloseHandle((*timer)->timerEvent) == FALSE) 
  398.     return VXItrd_RESULT_FATAL_ERROR;
  399.   delete *timer;
  400.   *timer = NULL;
  401.   return VXItrd_RESULT_SUCCESS;
  402. }
  403. /**
  404.  * Purpose  Puts the current thread to sleep for a configurable duration.
  405.  *          Due to other activities of the machine, the delay is the minimum
  406.  *          length that the timer will wait.
  407.  *
  408.  * @param   timer  a pointer to a timer
  409.  * @param   millisecondDelay  the minimum number of milliseconds to wait
  410.  * @param   interrupted  a pointer (may optionally be NULL) indicating whether
  411.  *            or not the sleep was interrupted by VXItrdTimerWake.
  412.  * @return  VXItrdResult of operation.  Return SUCCESS if timer could sleep.
  413.  *
  414.  */
  415. VXITRD_API VXItrdResult VXItrdTimerSleep(VXItrdTimer *timer,
  416.  VXIint millisecondDelay,
  417.  VXIbool *interrupted)
  418. {
  419.   if ((timer == NULL) || (millisecondDelay < 0)) 
  420.     return VXItrd_RESULT_INVALID_ARGUMENT;
  421.   switch (WaitForSingleObject(timer->timerEvent, millisecondDelay)) {
  422.   case WAIT_OBJECT_0:
  423.     if (interrupted != NULL) *interrupted = 1;
  424.     break;
  425.   case WAIT_TIMEOUT:
  426.     if (interrupted != NULL) *interrupted = 0;
  427.     break;
  428.   default:
  429.     return VXItrd_RESULT_FATAL_ERROR;
  430.   }
  431.   return VXItrd_RESULT_SUCCESS;
  432. }
  433. /**
  434.  * Purpose  Wakes a sleeping thread, if the target is not already sleeping
  435.  *          it immediately wakes when it tries to sleep the next time.
  436.  *
  437.  * @param   timer  a pointer to a timer
  438.  * @return  VXItrdResult of operation.  Return SUCCESS if timer could wake.
  439.  *
  440.  */
  441. VXITRD_API VXItrdResult VXItrdTimerWake(VXItrdTimer *timer)
  442. {
  443.   if (timer == NULL) return VXItrd_RESULT_INVALID_ARGUMENT;
  444.   if (SetEvent(timer->timerEvent) == 0) return VXItrd_RESULT_FATAL_ERROR;
  445.   return VXItrd_RESULT_SUCCESS;
  446. }
  447. /**
  448.  * Initialize the TRD utilities library
  449.  *
  450.  * @param threadStackSize  Stack size to use when creating new threads.
  451.  *                         Pass 0 to use the default (OS-specific) size,
  452.  *                         usually this means new threads will use the
  453.  *                         same stack size as the main (parent) process.
  454.  *
  455.  * @return VXItrd_RESULT_SUCCESS if sucess, different value on failure
  456.  */
  457. VXITRD_API VXItrdResult VXItrdInit (VXIint32 threadStackSize)
  458. {
  459.   if (threadStackSize >= 0)
  460.     g_threadStackSize = threadStackSize;
  461.   return VXItrd_RESULT_SUCCESS;
  462. }
  463. /**
  464.  * Shutdown the TRD utilities library
  465.  *
  466.  * @return VXItrd_RESULT_SUCCESS if sucess, different value on failure
  467.  */
  468. VXITRD_API VXItrdResult VXItrdShutDown ()
  469. {
  470.   return VXItrd_RESULT_SUCCESS;
  471. }