/*---------------------------------------------------------------------- | NPT_PosixQueue::Pop +---------------------------------------------------------------------*/ NPT_Result NPT_PosixQueue::Pop(NPT_QueueItem*& item, NPT_Timeout timeout) { struct timespec timed; struct timeval now; // get current time from system if (gettimeofday(&now, NULL)) { return NPT_FAILURE; } now.tv_usec += timeout * 1000; if (now.tv_usec >= 1000000) { now.tv_sec += now.tv_usec / 1000000; now.tv_usec = now.tv_usec % 1000000; } // setup timeout timed.tv_sec = now.tv_sec; timed.tv_nsec = now.tv_usec * 1000; // lock the mutex that protects the list if (pthread_mutex_lock(&m_Mutex)) { return NPT_FAILURE; } NPT_Result result; if (timeout) { while ((result = m_Items.PopHead(item)) == NPT_ERROR_LIST_EMPTY) { // no item in the list, wait for one //NPT_Debug(":: NPT_PosixQueue::Pop - waiting for queue to fill up\n"); if (timeout == NPT_TIMEOUT_INFINITE) { pthread_cond_wait(&m_CanPushOrPopCondition, &m_Mutex); } else { int wait_res = pthread_cond_timedwait(&m_CanPushOrPopCondition, &m_Mutex, &timed); if (wait_res == ETIMEDOUT) { result = NPT_ERROR_TIMEOUT; break; } } } } else { result = m_Items.PopHead(item); } // if the list was previously full, signal the condition // to wake up the waiting thread if (m_MaxItems && (result == NPT_SUCCESS)) { if (m_Items.GetItemCount() == m_MaxItems-1) { pthread_cond_signal(&m_CanPushOrPopCondition); } } // unlock the mutex pthread_mutex_unlock(&m_Mutex); return result; }
/*---------------------------------------------------------------------- | NPT_PosixQueue::Pop +---------------------------------------------------------------------*/ NPT_Result NPT_PosixQueue::Pop(NPT_QueueItem*& item, NPT_Timeout timeout) { struct timespec timed; if (timeout != NPT_TIMEOUT_INFINITE) { NPT_CHECK(GetTimeOut(timeout, timed)); } // lock the mutex that protects the list if (pthread_mutex_lock(&m_Mutex)) { return NPT_FAILURE; } NPT_Result result; if (timeout) { while ((result = m_Items.PopHead(item)) == NPT_ERROR_LIST_EMPTY) { // no item in the list, wait for one ++m_PoppersWaitingCount; if (timeout == NPT_TIMEOUT_INFINITE) { pthread_cond_wait(&m_CanPopCondition, &m_Mutex); --m_PoppersWaitingCount; } else { int wait_res = pthread_cond_timedwait(&m_CanPopCondition, &m_Mutex, &timed); --m_PoppersWaitingCount; if (wait_res == ETIMEDOUT) { result = NPT_ERROR_TIMEOUT; break; } } if (m_Aborting) { result = NPT_ERROR_INTERRUPTED; break; } } } else { result = m_Items.PopHead(item); } // wake up any thread that my be waiting to push if (m_MaxItems && (result == NPT_SUCCESS) && m_PushersWaitingCount) { pthread_cond_broadcast(&m_CanPushCondition); } // unlock the mutex pthread_mutex_unlock(&m_Mutex); return result; }
/*---------------------------------------------------------------------- | NPT_PSPQueue::Pop +---------------------------------------------------------------------*/ NPT_Result NPT_PSPQueue::Pop(NPT_QueueItem*& item, NPT_Boolean blocking) { // lock the mutex that protects the list m_Items.Lock(); NPT_Result result; //if (blocking) { // while ((result = m_Items.PopHead(item)) == NPT_ERROR_LIST_EMPTY) { // // no item in the list, wait for one // //NPT_Debug(":: NPT_PSPQueue::Pop - waiting for queue to fill up\n"); // pthread_cond_wait(&m_CanPushOrPopCondition, &m_Mutex); // } //} else { result = m_Items.PopHead(item); //} // if the list was previously full, signal the condition // to wake up the waiting thread //if (m_MaxItems && (result == NPT_SUCCESS)) { // if (m_Items.GetItemCount() == m_MaxItems-1) { // pthread_cond_signal(&m_CanPushOrPopCondition); // } //} // unlock the mutex m_Items.Unlock(); return result; }
/*---------------------------------------------------------------------- | NPT_Win32Queue::Pop +---------------------------------------------------------------------*/ NPT_Result NPT_Win32Queue::Pop(NPT_QueueItem*& item, NPT_Timeout timeout) { // default value item = NULL; // lock the mutex that protects the list NPT_CHECK(m_Mutex.Lock()); NPT_Result result; if (timeout) { while ((result = m_Items.PopHead(item)) == NPT_ERROR_LIST_EMPTY) { // no item in the list, wait for one // reset the condition to indicate that the queue is empty m_CanPopCondition->Reset(); // unlock the mutex so that another thread can push m_Mutex.Unlock(); // wait for the condition to signal that we can pop NPT_Result result = m_CanPopCondition->Wait(timeout); if (NPT_FAILED(result)) return result; // relock the mutex so that we can check the list again NPT_CHECK(m_Mutex.Lock()); } } else { result = m_Items.PopHead(item); } if (m_MaxItems && (result == NPT_SUCCESS)) { // wake up the threads waiting to push m_CanPushCondition->Signal(); } // unlock the mutex m_Mutex.Unlock(); return result; }