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