/** * Copyright (c) 2025 Dominic Masters * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #include "thread.h" #include "util/memory.h" #include "assert/assert.h" void threadInit(thread_t *thread, const threadcallback_t callback) { assertNotNull(thread, "Thread cannot be NULL."); assertNotNull(callback, "Thread callback cannot be NULL."); memoryZero(thread, sizeof(thread_t)); thread->state = THREAD_STATE_STOPPED; thread->callback = callback; #if THREAD_PTHREAD thread->threadId = 0; #endif } void threadStartRequest(thread_t *thread) { assertNotNull(thread, "Thread cannot be NULL."); threadMutexLock(&thread->stateMutex); thread->state = THREAD_STATE_STARTING; threadMutexUnlock(&thread->stateMutex); #if THREAD_PTHREAD assertTrue(thread->threadId == 0, "Thread id not 0."); pthread_create( &thread->threadId, NULL, (void * (*)(void *))threadHandler, thread ); pthread_detach(thread->threadId); #endif } void threadStopRequest(thread_t *thread) { assertNotNull(thread, "Thread cannot be NULL."); threadMutexLock(&thread->stateMutex); if(thread->state != THREAD_STATE_STOPPED) { thread->state = THREAD_STATE_STOP_REQUESTED; } threadMutexUnlock(&thread->stateMutex); } void threadStart(thread_t *thread) { assertNotNull(thread, "Thread cannot be NULL."); threadStartRequest(thread); threadMutexLock(&thread->stateMutex); threadMutexWaitLock(&thread->stateMutex); threadMutexUnlock(&thread->stateMutex); printf("Thread is now running.\n"); } void threadStop(thread_t *thread) { assertNotNull(thread, "Thread cannot be NULL."); threadStopRequest(thread); threadMutexLock(&thread->stateMutex); while(thread->state != THREAD_STATE_STOPPED) { threadMutexWaitLock(&thread->stateMutex); } threadMutexUnlock(&thread->stateMutex); } bool_t threadShouldStop(thread_t *thread) { bool_t state; assertNotNull(thread, "Thread cannot be NULL."); threadMutexLock(&thread->stateMutex); switch(thread->state) { case THREAD_STATE_STOPPED: case THREAD_STATE_STOP_REQUESTED: state = true; break; default: state = false; break; } threadMutexUnlock(&thread->stateMutex); return state; } #if THREAD_PTHREAD void * threadHandler(thread_t *thread) { assertNotNull(thread, "Thread cannot be NULL."); threadMutexLock(&thread->stateMutex); thread->state = THREAD_STATE_RUNNING; threadMutexSignal(&thread->stateMutex); threadMutexUnlock(&thread->stateMutex); // Send to callback. thread->callback(thread); threadMutexLock(&thread->stateMutex); thread->state = THREAD_STATE_STOPPED; threadMutexSignal(&thread->stateMutex); threadMutexUnlock(&thread->stateMutex); thread->threadId = 0; return NULL; } #endif