📄 sbtrdpthreads.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. * ***********************************************************************/ /***************************************************************************** ***************************************************************************** * SBtrd API implementation * * This provides the Linux implementation of the VXItrd API for basic * thread operations and locks. Unlike most of the other VXI APIs, * this is implemented in a library (on Windows a DLL with a specific * name, on other operating systems as a static, shared, or dynamic * library). Implementations of this API are operating system * dependant. * * To avoid cyclic dependancies, this does not perform logging. Clients * must do error logging themselves based on passed return codes. * ***************************************************************************** *****************************************************************************/ // -----1=0-------2=0-------3=0-------4=0-------5=0-------6=0-------7=0-------8 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <signal.h> #include <pthread.h> #include <sys/time.h> #include <sys/types.h> #define VXITRD_EXPORTS #include "VXItrd.h" // Header for this API #ifndef NDEBUG #include <assert.h> #endif extern "C" { struct VXItrdMutex { pthread_mutex_t mutex; #if ( ! defined(NDEBUG) ) && ( ! defined(VXITRD_RECURSIVE_MUTEX) ) volatile bool locked; #endif }; } typedef enum VXItrdThreadState { STATE_STARTING = 0, STATE_RUNNING = 1, STATE_EXITED = 2 } VXItrdThreadState; extern "C" { struct VXItrdThread { pthread_t thread; // Thread handle volatile VXItrdThreadState state; // Thread state VXItrdMutex *refCountMutex; // For reference count protection volatile VXIulong refCount; // References to this structure VXItrdThreadStartFunc thread_function; // user's thread function VXItrdThreadArg thread_arg; // user's thread argument }; } extern "C" { struct VXItrdTimer { volatile VXIbool isSleeping; /* If 1, thread is currently sleeping */ volatile VXIbool wakeUp; /* If 1, thread will ignore the next Sleep() */ }; } static VXIint32 g_threadStackSize = 0; // -----1=0-------2=0-------3=0-------4=0-------5=0-------6=0-------7=0-------8 /** * Internal utility function for sleeping */ static VXItrdResult VXItrdSleep(VXIint millisecondDelay) { // Do not want to use usleep( ), non-portable and it is usually implemented // via signals which may mess up other software in the system which is // also trying to use signals. Note that it is very important to set up // the timer each time as on some OSes (like Linux) the timeout var is // modified to indicate the actual time slept. struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = millisecondDelay * 1000; if (select (0, NULL, NULL, NULL, &timeout) < 0) return VXItrd_RESULT_SYSTEM_ERROR; return VXItrd_RESULT_SUCCESS; } /** * Creates a new mutex initialized to the unlocked state. If the calling * thread terminates, the created mutex is not automatically deallocated as * it may be shared among multiple threads. * * @return -1 Fatal error (ex: system lacks necessary resources for creation) * 0 Success; valid mutex has been created */ VXITRD_API VXItrdResult VXItrdMutexCreate(VXItrdMutex **mutex) { if (mutex == NULL) return VXItrd_RESULT_INVALID_ARGUMENT; *mutex = NULL; // Create the wrapper object */ VXItrdMutex *result = new VXItrdMutex; if (result == NULL) return VXItrd_RESULT_OUT_OF_MEMORY; #if ( ! defined(NDEBUG) ) && ( ! defined(VXITRD_RECURSIVE_MUTEX) ) result->locked = false; #endif // Create the critical section */ int rc; pthread_mutexattr_t mutexattr; // Create and configure mutex attributes for recursive mutex rc = pthread_mutexattr_init(&mutexattr); if (rc != 0) { delete result; return VXItrd_RESULT_NON_FATAL_ERROR; } #ifndef _unixware7_ rc = pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE); if (rc != 0) { pthread_mutexattr_destroy(&mutexattr); delete result; return VXItrd_RESULT_NON_FATAL_ERROR; } #endif // Initialize mutex with attributes rc = pthread_mutex_init(&result->mutex, &mutexattr); if (rc != 0) { pthread_mutexattr_destroy(&mutexattr); delete result; return VXItrd_RESULT_NON_FATAL_ERROR; } rc = pthread_mutexattr_destroy(&mutexattr); if (rc != 0) { pthread_mutex_destroy(&result->mutex); delete result; return VXItrd_RESULT_NON_FATAL_ERROR; } *mutex = result; return VXItrd_RESULT_SUCCESS; } /** * Deletes an existing mutex. It is illegal to delete a locked mutex. * * @return -1 Fatal error (ex: invalid mutex) * 0 Success; mutex has been destroyed * 1 Mutex is locked */ VXITRD_API VXItrdResult VXItrdMutexDestroy(VXItrdMutex **mutex) { if ((mutex == NULL) || (*mutex == NULL)) return VXItrd_RESULT_INVALID_ARGUMENT; #if ( ! defined(NDEBUG) ) && ( ! defined(VXITRD_RECURSIVE_MUTEX) ) // Check the lock state if ( (*mutex)->locked ) { assert ("VXItrdMutexDestroy( ) on locked mutex" == NULL); return VXItrd_RESULT_FATAL_ERROR; } #endif int rc = pthread_mutex_destroy(&(*mutex)->mutex); if (rc != 0) { return VXItrd_RESULT_NON_FATAL_ERROR; } delete *mutex; *mutex = NULL; return VXItrd_RESULT_SUCCESS; } /** * Locks an existing mutex. If the mutex is already locked, the thread waits * for the mutex to become available. * * @return: -1 Fatal error (ex: invalid mutex or deadlock detected) * 0 Success; mutex is now locked * 1 Mutex already locked by current thread. */ VXITRD_API VXItrdResult VXItrdMutexLock(VXItrdMutex *mutex) { if (mutex == NULL) return VXItrd_RESULT_INVALID_ARGUMENT; int rc = pthread_mutex_lock(&mutex->mutex); if (rc != 0) { return VXItrd_RESULT_NON_FATAL_ERROR; } #if ( ! defined(NDEBUG) ) && ( ! defined(VXITRD_RECURSIVE_MUTEX) ) // Check the lock state if ( mutex->locked ) { // Should not be locking the same mutex twice, very OS dependant // and not gauranteed by VXItrdMutex assert ("VXItrdMutexLock( ) on already locked mutex" == NULL); return VXItrd_RESULT_FATAL_ERROR; } else { mutex->locked = true; } #endif return VXItrd_RESULT_SUCCESS; } /** * Unlocks a mutex owned by the thread. * * @return: -1 Fatal error (ex: invalid mutex) * 0 Success; mutex no longer owned by calling thread * 1 Mutex not owned by thread. */ VXITRD_API VXItrdResult VXItrdMutexUnlock(VXItrdMutex *mutex) { if (mutex == NULL) return VXItrd_RESULT_INVALID_ARGUMENT; #if ( ! defined(NDEBUG) ) && ( ! defined(VXITRD_RECURSIVE_MUTEX) ) // Check the lock state if ( ! mutex->locked ) { // Unlocking a mutex that wasn't locked assert ("VXItrdMutexUnlock( ) on unlocked mutex" == NULL); return VXItrd_RESULT_FATAL_ERROR; } else { mutex->locked = false; } #endif int rc = pthread_mutex_unlock(&mutex->mutex); if (rc != 0) { return VXItrd_RESULT_NON_FATAL_ERROR; } return VXItrd_RESULT_SUCCESS; } /** * Internal: wrapper functions for starting/cleaning up threads */ static void VXItrdThreadCleanup(VXItrdThreadArg userData) { VXItrdThread *thread = (VXItrdThread *) userData; // No longer active thread->state = STATE_EXITED; // Free our copy of the thread handle VXItrdThreadDestroyHandle (&thread); } static VXITRD_DEFINE_THREAD_FUNC(VXItrdThreadStart, userData) { VXItrdThread *thread = (VXItrdThread *) userData; // Set the state and register a cleanup function to finish it, // required for ThreadJoin( ) support thread->state = STATE_RUNNING; pthread_cleanup_push(VXItrdThreadCleanup, userData); // Call the user function (*thread->thread_function)(thread->thread_arg); // Cleanup, the 1 to pop causes the cleanup function to be invoked pthread_cleanup_pop(1); return NULL; // never gets called, just to eliminate compile warning } /** * Create a thread. Note: thread values are not supported on OS/2. * execution starts on the thread immediately. To pause execution * use a Mutex between the thread and the thread creator. * * @param thread the thread object to be created * @param thread_function the function for the thread to start execution on * @param thread_arg the arguments to the thread function * @return VXItrdResult of operation. Return SUCCESS if thread has been * created and started. * */ VXITRD_API VXItrdResult VXItrdThreadCreate(VXItrdThread **thread, VXItrdThreadStartFunc thread_function, VXItrdThreadArg thread_arg) { if ((thread == NULL) || (thread_function == NULL)) return VXItrd_RESULT_INVALID_ARGUMENT; *thread = NULL; // Create the wrapper object VXItrdThread *result = new VXItrdThread; if (result == NULL) return VXItrd_RESULT_OUT_OF_MEMORY; memset(result, 0, sizeof (VXItrdThread)); result->state = STATE_STARTING; result->refCount = 1; // 1 for parent result->thread_function = thread_function; result->thread_arg = thread_arg; if (VXItrdMutexCreate(&result->refCountMutex) != VXItrd_RESULT_SUCCESS) { VXItrdThreadDestroyHandle(&result); return VXItrd_RESULT_SYSTEM_ERROR; } // construct thread attribute
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -