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; }
/*--------------------------------------------------------------------*//*! * \brief Create a file based logger instance * \param fileName Name of the file where to put logs * \return qpTestLog instance, or DE_NULL if cannot create file *//*--------------------------------------------------------------------*/ qpTestLog* qpTestLog_createFileLog (const char* fileName, deUint32 flags) { qpTestLog* log = (qpTestLog*)deCalloc(sizeof(qpTestLog)); if (!log) return DE_NULL; DE_ASSERT(fileName && fileName[0]); /* must have filename. */ #if defined(DE_DEBUG) ContainerStack_reset(&log->containerStack); #endif qpPrintf("Writing test log into %s\n", fileName); /* Create output file. */ log->outputFile = fopen(fileName, "wb"); if (!log->outputFile) { qpPrintf("ERROR: Unable to open test log output file '%s'.\n", fileName); qpTestLog_destroy(log); return DE_NULL; } log->flags = flags; log->writer = qpXmlWriter_createFileWriter(log->outputFile, 0, !(flags & QP_TEST_LOG_NO_FLUSH)); log->lock = deMutex_create(DE_NULL); log->isSessionOpen = DE_FALSE; log->isCaseOpen = DE_FALSE; if (!log->writer) { qpPrintf("ERROR: Unable to create output XML writer to file '%s'.\n", fileName); qpTestLog_destroy(log); return DE_NULL; } if (!log->lock) { qpPrintf("ERROR: Unable to create mutex.\n"); qpTestLog_destroy(log); return DE_NULL; } beginSession(log); return log; }
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); } }