int LbqPollQueueElement(PLINKED_BLOCKING_QUEUE queueHead, void** data) { PLINKED_BLOCKING_QUEUE_ENTRY entry; if (queueHead->head == NULL) { return LBQ_NO_ELEMENT; } PltLockMutex(&queueHead->mutex); if (queueHead->head == NULL) { PltUnlockMutex(&queueHead->mutex); return LBQ_NO_ELEMENT; } entry = queueHead->head; queueHead->head = entry->flink; queueHead->currentSize--; if (queueHead->head == NULL) { LC_ASSERT(queueHead->currentSize == 0); queueHead->tail = NULL; PltClearEvent(&queueHead->containsDataEvent); } else { LC_ASSERT(queueHead->currentSize != 0); queueHead->head->blink = NULL; } *data = entry->data; PltUnlockMutex(&queueHead->mutex); return LBQ_SUCCESS; }
int LbqOfferQueueItem(PLINKED_BLOCKING_QUEUE queueHead, void* data, PLINKED_BLOCKING_QUEUE_ENTRY entry) { entry->flink = NULL; entry->data = data; PltLockMutex(&queueHead->mutex); if (queueHead->currentSize == queueHead->sizeBound) { PltUnlockMutex(&queueHead->mutex); return LBQ_BOUND_EXCEEDED; } if (queueHead->head == NULL) { LC_ASSERT(queueHead->currentSize == 0); LC_ASSERT(queueHead->tail == NULL); queueHead->head = entry; queueHead->tail = entry; entry->blink = NULL; } else { LC_ASSERT(queueHead->currentSize >= 1); LC_ASSERT(queueHead->head != NULL); queueHead->tail->flink = entry; entry->blink = queueHead->tail; queueHead->tail = entry; } queueHead->currentSize++; PltUnlockMutex(&queueHead->mutex); PltSetEvent(&queueHead->containsDataEvent); return LBQ_SUCCESS; }
static PLT_THREAD* findCurrentThread(void) { PLT_THREAD* current_thread; PltLockMutex(&thread_list_lock); current_thread = thread_head; while (current_thread != NULL) { #if defined(LC_WINDOWS) if (current_thread->tid == GetCurrentThreadId()) { #else if (pthread_equal(current_thread->thread, pthread_self())) { #endif break; } current_thread = current_thread->next; } PltUnlockMutex(&thread_list_lock); LC_ASSERT(current_thread != NULL); return current_thread; } #endif int PltCreateMutex(PLT_MUTEX* mutex) { #if defined(LC_WINDOWS) *mutex = CreateMutexEx(NULL, NULL, 0, MUTEX_ALL_ACCESS); if (!*mutex) { return -1; } return 0; #else return pthread_mutex_init(mutex, NULL); #endif }
DWORD WINAPI ThreadProc(LPVOID lpParameter) { struct thread_context* ctx = (struct thread_context*)lpParameter; #else void* ThreadProc(void* context) { struct thread_context* ctx = (struct thread_context*)context; #endif // Add this thread to the thread list PltLockMutex(&thread_list_lock); ctx->thread->next = thread_head; thread_head = ctx->thread; PltUnlockMutex(&thread_list_lock); ctx->entry(ctx->context); free(ctx); #if defined(LC_WINDOWS) return 0; #else return NULL; #endif } void PltSleepMs(int ms) { #if defined(LC_WINDOWS) WaitForSingleObjectEx(GetCurrentThread(), ms, FALSE); #else useconds_t usecs = ms * 1000; usleep(usecs); #endif }
void PltCloseThread(PLT_THREAD* thread) { PLT_THREAD* current_thread; PltLockMutex(&thread_list_lock); if (thread_head == thread) { // Remove the thread from the head thread_head = thread_head->next; } else { // Find the thread in the list current_thread = thread_head; while (current_thread != NULL) { if (current_thread->next == thread) { break; } current_thread = current_thread->next; } LC_ASSERT(current_thread != NULL); // Unlink this thread current_thread->next = thread->next; } PltUnlockMutex(&thread_list_lock); #if defined(LC_WINDOWS) CloseHandle(thread->termRequested); CloseHandle(thread->handle); #endif }
// This must be synchronized with LbqFlushQueueItems by the caller int LbqPeekQueueElement(PLINKED_BLOCKING_QUEUE queueHead, void** data) { if (queueHead->head == NULL) { return LBQ_NO_ELEMENT; } PltLockMutex(&queueHead->mutex); if (queueHead->head == NULL) { PltUnlockMutex(&queueHead->mutex); return LBQ_NO_ELEMENT; } *data = queueHead->head->data; PltUnlockMutex(&queueHead->mutex); return LBQ_SUCCESS; }
/* Flush the queue */ PLINKED_BLOCKING_QUEUE_ENTRY LbqFlushQueueItems(PLINKED_BLOCKING_QUEUE queueHead) { PLINKED_BLOCKING_QUEUE_ENTRY head; PltLockMutex(&queueHead->mutex); // Save the old head head = queueHead->head; // Reinitialize the queue to empty queueHead->head = NULL; queueHead->tail = NULL; queueHead->currentSize = 0; PltClearEvent(&queueHead->containsDataEvent); PltUnlockMutex(&queueHead->mutex); return head; }
int LbqWaitForQueueElement(PLINKED_BLOCKING_QUEUE queueHead, void** data) { PLINKED_BLOCKING_QUEUE_ENTRY entry; int err; for (;;) { err = PltWaitForEvent(&queueHead->containsDataEvent); if (err != PLT_WAIT_SUCCESS) { return LBQ_INTERRUPTED; } PltLockMutex(&queueHead->mutex); if (queueHead->head == NULL) { PltClearEvent(&queueHead->containsDataEvent); PltUnlockMutex(&queueHead->mutex); continue; } entry = queueHead->head; queueHead->head = entry->flink; queueHead->currentSize--; if (queueHead->head == NULL) { LC_ASSERT(queueHead->currentSize == 0); queueHead->tail = NULL; PltClearEvent(&queueHead->containsDataEvent); } else { LC_ASSERT(queueHead->currentSize != 0); queueHead->head->blink = NULL; } *data = entry->data; PltUnlockMutex(&queueHead->mutex); break; } return LBQ_SUCCESS; }