/* * Function: FetchWork * * Fetch a work item from the queue, blocking if none available. * Return value indicates of false indicates error/fatal condition. */ BOOL FetchWork ( WorkQueue* pq, void** ppw ) { DWORD rc; if (!pq) { queue_error("FetchWork", "NULL WorkQueue object"); return false; } if (!ppw) { queue_error("FetchWork", "NULL WorkItem object"); return false; } EnterCriticalSection(&pq->queueLock); *ppw = pq->items[pq->head]; /* For sanity's sake, zero out the pointer. */ pq->items[pq->head] = NULL; pq->head = (pq->head + 1) % WORKQUEUE_SIZE; rc = ReleaseSemaphore(pq->roomAvailable,1, NULL); LeaveCriticalSection(&pq->queueLock); if ( 0 == rc ) { queue_error_rc("FetchWork.ReleaseSemaphore()", GetLastError()); return false; } return true; }
/* * Function: SubmitWork * * Add work item to the queue, blocking if no room available. * Return value indicates of false indicates error/fatal condition. */ BOOL SubmitWork ( WorkQueue* pq, void* pw ) { DWORD rc; if (!pq) { queue_error("SubmitWork", "NULL WorkQueue object"); return false; } if (!pw) { queue_error("SubmitWork", "NULL WorkItem object"); return false; } /* Block waiting for work item to become available */ if ( (rc = WaitForSingleObject( pq->roomAvailable, INFINITE)) != WAIT_OBJECT_0 ) { queue_error_rc("SubmitWork.WaitForSingleObject(workAvailable)", ( (WAIT_FAILED == rc) ? GetLastError() : rc)); return false; } EnterCriticalSection(&pq->queueLock); pq->items[pq->tail] = pw; pq->tail = (pq->tail + 1) % WORKQUEUE_SIZE; rc = ReleaseSemaphore(pq->workAvailable,1, NULL); LeaveCriticalSection(&pq->queueLock); if ( 0 == rc ) { queue_error_rc("SubmitWork.ReleaseSemaphore()", GetLastError()); return false; } return true; }
static void add_error_log_rec ( error_log_rec_t *log_rec_p, STRTAB_str_t filename, int lineno, idl_error_list_t *msgs ) { if (log_rec_p->lineno < lineno) { if (log_rec_p->links.asBinTree.right != NULL) add_error_log_rec(log_rec_p->links.asBinTree.right, filename, lineno, msgs); else log_rec_p->links.asBinTree.right = alloc_log_rec(filename, lineno, msgs); return; } if (log_rec_p->lineno > lineno) { if (log_rec_p->links.asBinTree.left != NULL) add_error_log_rec(log_rec_p->links.asBinTree.left, filename, lineno, msgs); else log_rec_p->links.asBinTree.left = alloc_log_rec(filename, lineno, msgs); return; } if (log_rec_p->lineno == lineno) queue_error(log_rec_p, filename, msgs); }
/* * Function: NewWorkQueue * * The queue constructor - semaphores are initialised to match * max number of queue entries. * */ WorkQueue* NewWorkQueue() { WorkQueue* wq = (WorkQueue*)malloc(sizeof(WorkQueue)); if (!wq) { queue_error("NewWorkQueue", "malloc() failed"); return wq; } memset(wq, 0, sizeof *wq); InitializeCriticalSection(&wq->queueLock); wq->workAvailable = newSemaphore(0, WORKQUEUE_SIZE); wq->roomAvailable = newSemaphore(WORKQUEUE_SIZE, WORKQUEUE_SIZE); /* Fail if we were unable to create any of the sync objects. */ if ( NULL == wq->workAvailable || NULL == wq->roomAvailable ) { FreeWorkQueue(wq); return NULL; } return wq; }
/* * Function: GetWork * * Fetch a work item from the queue, blocking if none available. * Return value indicates of false indicates error/fatal condition. */ BOOL GetWork ( WorkQueue* pq, void** ppw ) { DWORD rc; if (!pq) { queue_error("GetWork", "NULL WorkQueue object"); return false; } if (!ppw) { queue_error("GetWork", "NULL WorkItem object"); return false; } /* Block waiting for work item to become available */ if ( (rc = WaitForSingleObject( pq->workAvailable, INFINITE)) != WAIT_OBJECT_0 ) { queue_error_rc("GetWork.WaitForSingleObject(workAvailable)", ( (WAIT_FAILED == rc) ? GetLastError() : rc)); return false; } return FetchWork(pq,ppw); }