static deTimerThread* deTimerThread_create (deTimerCallback callback, void* arg, int interval, TimerState state) { deTimerThread* thread = (deTimerThread*)deCalloc(sizeof(deTimerThread)); DE_ASSERT(state == TIMERSTATE_INTERVAL || state == TIMERSTATE_SINGLE); if (!thread) return DE_NULL; thread->callback = callback; thread->callbackArg = arg; thread->interval = interval; thread->lock = deMutex_create(DE_NULL); thread->state = state; thread->thread = deThread_create(timerThread, thread, DE_NULL); if (!thread->thread) { deMutex_destroy(thread->lock); deFree(thread); return DE_NULL; } return thread; }
void deTimer_disable (deTimer* timer) { if (!timer->curThread) return; deMutex_lock(timer->curThread->lock); if (timer->curThread->state != TIMERSTATE_DISABLED) { /* Just set state to disabled and destroy thread handle. */ /* \note Assumes that deThread_destroy() can be called while thread is still running * and it will not terminate the thread. */ timer->curThread->state = TIMERSTATE_DISABLED; deThread_destroy(timer->curThread->thread); timer->curThread->thread = 0; deMutex_unlock(timer->curThread->lock); /* Thread will destroy timer->curThread. */ } else { /* Single timer has expired - we must destroy whole thread structure. */ deMutex_unlock(timer->curThread->lock); deThread_destroy(timer->curThread->thread); deMutex_destroy(timer->curThread->lock); deFree(timer->curThread); } timer->curThread = DE_NULL; }
/*--------------------------------------------------------------------*//*! * \brief Destroy a logger instance * \param a qpTestLog instance *//*--------------------------------------------------------------------*/ void qpTestLog_destroy (qpTestLog* log) { DE_ASSERT(log); if (log->isSessionOpen) endSession(log); if (log->writer) qpXmlWriter_destroy(log->writer); if (log->outputFile) fclose(log->outputFile); if (log->lock) deMutex_destroy(log->lock); deFree(log); }
static void timerThread (void* arg) { deTimerThread* thread = (deTimerThread*)arg; int numCallbacks = 0; deBool destroy = DE_TRUE; deInt64 lastCallback = (deInt64)deGetMicroseconds(); for (;;) { int sleepTime = 0; deMutex_lock(thread->lock); if (thread->state == TIMERSTATE_SINGLE && numCallbacks > 0) { destroy = DE_FALSE; /* Will be destroyed by deTimer_disable(). */ thread->state = TIMERSTATE_DISABLED; break; } else if (thread->state == TIMERSTATE_DISABLED) break; deMutex_unlock(thread->lock); sleepTime = thread->interval - (int)(((deInt64)deGetMicroseconds()-lastCallback)/1000); if (sleepTime > 0) deSleep(sleepTime); lastCallback = (deInt64)deGetMicroseconds(); thread->callback(thread->callbackArg); numCallbacks += 1; } /* State lock is held when loop is exited. */ deMutex_unlock(thread->lock); if (destroy) { /* Destroy thread except thread->thread. */ deMutex_destroy(thread->lock); deFree(thread); } }
void deMutex_selfTest (void) { /* Default mutex from single thread. */ { deMutex mutex = deMutex_create(DE_NULL); deBool ret; DE_TEST_ASSERT(mutex); deMutex_lock(mutex); deMutex_unlock(mutex); /* Should succeed. */ ret = deMutex_tryLock(mutex); DE_TEST_ASSERT(ret); deMutex_unlock(mutex); deMutex_destroy(mutex); } /* Recursive mutex. */ { deMutexAttributes attrs; deMutex mutex; int ndx; int numLocks = 10; deMemset(&attrs, 0, sizeof(attrs)); attrs.flags = DE_MUTEX_RECURSIVE; mutex = deMutex_create(&attrs); DE_TEST_ASSERT(mutex); for (ndx = 0; ndx < numLocks; ndx++) deMutex_lock(mutex); for (ndx = 0; ndx < numLocks; ndx++) deMutex_unlock(mutex); deMutex_destroy(mutex); } /* Mutex and threads. */ { deMutex mutex; deThread thread; mutex = deMutex_create(DE_NULL); DE_TEST_ASSERT(mutex); deMutex_lock(mutex); thread = deThread_create(mutexTestThr1, &mutex, DE_NULL); DE_TEST_ASSERT(thread); deSleep(100); deMutex_unlock(mutex); deMutex_lock(mutex); deMutex_unlock(mutex); deThread_join(thread); deThread_destroy(thread); deMutex_destroy(mutex); } /* A bit more complex mutex test. */ { MutexData2 data; deThread threads[2]; int ndx; data.mutex = deMutex_create(DE_NULL); DE_TEST_ASSERT(data.mutex); data.counter = 0; data.counter2 = 0; data.maxVal = 1000; deMutex_lock(data.mutex); for (ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(threads); ndx++) { threads[ndx] = deThread_create(mutexTestThr2, &data, DE_NULL); DE_TEST_ASSERT(threads[ndx]); } deMutex_unlock(data.mutex); for (ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(threads); ndx++) { deBool ret = deThread_join(threads[ndx]); DE_TEST_ASSERT(ret); deThread_destroy(threads[ndx]); } DE_TEST_ASSERT(data.counter == data.counter2); DE_TEST_ASSERT(data.maxVal == data.counter); deMutex_destroy(data.mutex); } /* tryLock() deadlock test. */ { deThread thread; deMutex mutex = deMutex_create(DE_NULL); deBool ret; DE_TEST_ASSERT(mutex); deMutex_lock(mutex); thread = deThread_create(mutexTestThr3, &mutex, DE_NULL); DE_TEST_ASSERT(mutex); ret = deThread_join(thread); DE_TEST_ASSERT(ret); deMutex_unlock(mutex); deMutex_destroy(mutex); deThread_destroy(thread); } }