📄 sbtrdpthreads.cpp
字号:
pthread_attr_t thread_attr;
int prc = pthread_attr_init(&thread_attr);
if (prc != 0) {
VXItrdThreadDestroyHandle(&result);
return VXItrd_RESULT_NON_FATAL_ERROR;
}
// configure thread attribute
#ifdef USE_DETACHED_THREADS
prc = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
if (prc != 0) {
pthread_attr_destroy(&thread_attr);
VXItrdThreadDestroyHandle(&result);
return VXItrd_RESULT_NON_FATAL_ERROR;
}
#else
// use joinable threads
// this is default - no work required
#endif
// Set the thread's stack size. A zero value means 'let the OS decide'
if (g_threadStackSize > 0)
pthread_attr_setstacksize(&thread_attr, g_threadStackSize);
// Start the thread using our wrapper function
result->refCount++; // for child
prc = pthread_create(&result->thread, &thread_attr, VXItrdThreadStart,
(VXItrdThreadArg) result);
pthread_attr_destroy(&thread_attr);
if (prc != 0) {
result->refCount--;
VXItrdThreadDestroyHandle(&result);
return VXItrd_RESULT_NON_FATAL_ERROR;
}
*thread = result;
return VXItrd_RESULT_SUCCESS;
}
/**
* Destroy a thread handle
*
* Note: this does NOT stop or destroy the thread, it just releases
* the handle for accessing it. If this is not done, a memory leak
* occurs, so if the creator of the thread never needs to communicate
* with the thread again it should call this immediately after the
* create if the create was successful.
*
* @param thread Handle to the thread to destroy
*
* @result VXItrdResult 0 on success
*/
VXITRD_API VXItrdResult VXItrdThreadDestroyHandle(VXItrdThread **thread)
{
if ((thread == NULL) || (*thread == NULL))
return VXItrd_RESULT_INVALID_ARGUMENT;
// Decrement ref count
VXIulong refs = 0;
if ((*thread)->refCountMutex) {
VXItrdMutexLock ((*thread)->refCountMutex);
(*thread)->refCount--;
refs = (*thread)->refCount;
VXItrdMutexUnlock ((*thread)->refCountMutex);
}
if (refs == 0) {
// No longer needed
if ((*thread)->refCountMutex)
VXItrdMutexDestroy (&(*thread)->refCountMutex);
delete *thread;
}
*thread = NULL;
return VXItrd_RESULT_SUCCESS;
}
/**
* Terminate a thread. Called by the thread on exit.
*
* @param status Exit code for the thread
* @result N/A, never returns
*/
VXITRD_API void VXItrdThreadExit(VXItrdThreadArg status)
{
pthread_exit(status);
}
/**
* Causes the calling thread to wait for the termination of a specified
* 'thread' with a specified timeout, in milliseconds.
*
* @param thread the 'thread' that is waited for its termination.
* @param status contains the exit value of the thread's start routine.
* @return VXItrdResult of operation. Return SUCCESS if specified 'thread'
* terminating.
*/
VXITRD_API VXItrdResult VXItrdThreadJoin(VXItrdThread *thread,
VXItrdThreadArg *status,
long timeout)
{
if ((thread == NULL ) || (status == NULL) || (timeout < -1))
return VXItrd_RESULT_INVALID_ARGUMENT;
VXItrdResult rc = VXItrd_RESULT_SUCCESS;
if (timeout == -1) {
// Wait forever
if (pthread_join(thread->thread, status) != 0)
rc = VXItrd_RESULT_SYSTEM_ERROR;
} else {
// Wait with a timeout, we just do a polling implementation
long remainingMsec = timeout;
while ((remainingMsec > 0) && (thread->state != STATE_EXITED) &&
(rc == VXItrd_RESULT_SUCCESS)) {
if (remainingMsec > 50) {
rc = VXItrdSleep (50);
remainingMsec -= 50;
} else {
rc = VXItrdSleep (remainingMsec);
remainingMsec = 0;
}
}
if (rc == VXItrd_RESULT_SUCCESS) {
if (thread->state == STATE_EXITED) {
// Collect the thread
if (pthread_join(thread->thread, status) != 0)
rc = VXItrd_RESULT_SYSTEM_ERROR;
} else {
rc = VXItrd_RESULT_FAILURE;
}
}
}
return rc;
}
/**
* Get the thread ID for the specified thread
*
* @param thread Handle to the thread to get the ID for
*
* @result Thread ID number
*/
VXITRD_API VXIthreadID VXItrdThreadGetIDFromHandle(VXItrdThread *thread)
{
if (thread == NULL)
return (VXIthreadID) -1;
return thread->thread;
}
/**
* Get the ID of the current handle.
*
* @return The current thread handle identifier.
*
*/
VXITRD_API VXIthreadID VXItrdThreadGetID(void)
{
return pthread_self();
}
/**
* Purpose Yield the process schedule in the current thread.
*
* @return void
*
*/
VXITRD_API void VXItrdThreadYield(void)
{
#ifndef NDEBUG
assert (sched_yield() == 0);
#else
sched_yield();
#endif
}
/**
* Create a timer
*
* @param timer a pointer to a timer
* @return VXItrdResult of operation. Return SUCCESS if timer has been
* created
*
*/
VXITRD_API VXItrdResult VXItrdTimerCreate(VXItrdTimer **timer)
{
if (timer == NULL)
return VXItrd_RESULT_INVALID_ARGUMENT;
VXItrdTimer *result = new VXItrdTimer;
if (result == NULL)
return VXItrd_RESULT_OUT_OF_MEMORY;
// Initialize all data
result->isSleeping = FALSE;
result->wakeUp = FALSE;
*timer = result;
return VXItrd_RESULT_SUCCESS;
}
/**
* Destroy a timer
*
* @param timer a pointer to a timer
* @return VXItrdResult of operation. Return SUCCESS if timer has been
* created
*
*/
VXITRD_API VXItrdResult VXItrdTimerDestroy(VXItrdTimer **timer)
{
if ((timer == NULL) || (*timer == NULL))
return VXItrd_RESULT_INVALID_ARGUMENT;
// Don't leave the corresponding thread in a suspended state.
VXItrdResult rc = VXItrd_RESULT_SUCCESS;
if ((*timer)->isSleeping) {
VXItrdTimerWake(*timer);
// Wait for the sleeping thread to wake up, note that on some OSes
// like Linux the timeout is modified to give the actual amount of
// time slept so need to re-initialize each time
while (((*timer)->isSleeping) &&
((rc = VXItrdSleep (50)) == VXItrd_RESULT_SUCCESS))
; // keep going
}
delete *timer;
*timer = NULL;
return rc;
}
/**
* Puts the current thread to sleep for a configurable duration.
* Due to other activities of the machine, the delay is the minimum
* length that the timer will wait.
*
* @param timer a pointer to a timer
* @param millisecondDelay the minimum number of milliseconds to wait
* @param interrupted a pointer (may optionally be NULL) indicating whether
* or not the sleep was interrupted by VXItrdTimerWake.
* @return VXItrdResult of operation. Return SUCCESS if timer could sleep.
*
*/
VXITRD_API VXItrdResult VXItrdTimerSleep(VXItrdTimer *timer,
VXIint millisecondDelay,
VXIbool *interrupted)
{
if ((timer == NULL) || (millisecondDelay < 0))
return VXItrd_RESULT_INVALID_ARGUMENT;
if (timer->isSleeping == TRUE)
return VXItrd_RESULT_FATAL_ERROR;
timer->isSleeping = TRUE;
// Sleep, we just do a polling implementation
VXItrdResult rc = VXItrd_RESULT_SUCCESS;
VXIint remainingMsec = millisecondDelay;
while ((remainingMsec > 0) && (timer->wakeUp == FALSE) &&
(rc == VXItrd_RESULT_SUCCESS)) {
if (remainingMsec > 50) {
rc = VXItrdSleep (50);
remainingMsec -= 50;
} else {
rc = VXItrdSleep (remainingMsec);
remainingMsec = 0;
}
}
if (timer->wakeUp) {
if (interrupted)
*interrupted = TRUE;
timer->wakeUp = FALSE;
} else if (interrupted) {
*interrupted = FALSE;
}
timer->isSleeping = FALSE;
return VXItrd_RESULT_SUCCESS;
}
/**
* Wakes a sleeping thread, if the target is not already sleeping
* it immediately wakes when it tries to sleep the next time.
*
* @param timer a pointer to a timer
* @return VXItrdResult of operation. Return SUCCESS if timer could wake.
*
*/
VXITRD_API VXItrdResult VXItrdTimerWake(VXItrdTimer *timer)
{
if (timer == NULL)
return VXItrd_RESULT_INVALID_ARGUMENT;
timer->wakeUp = TRUE;
return VXItrd_RESULT_SUCCESS;
}
/**
* Initialize the TRD utilities library
*
* @param threadStackSize Stack size to use when creating new threads.
* Pass 0 to use the default (OS-specific) size,
* usually this means new threads will use the
* same stack size as the main (parent) process.
*
* @return VXItrd_RESULT_SUCCESS if sucess, different value on failure
*/
VXITRD_API VXItrdResult VXItrdInit (VXIint32 threadStackSize)
{
g_threadStackSize = threadStackSize;
return VXItrd_RESULT_SUCCESS;
}
/**
* Shutdown the TRD utilities library
*
* @return VXItrd_RESULT_SUCCESS if sucess, different value on failure
*/
VXITRD_API VXItrdResult VXItrdShutDown ()
{
return VXItrd_RESULT_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -