📄 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 + -