Пример #1
0
/*----------------------------------------------------------------------
|   NPT_Win32SharedVariable::WaitWhileOrUntilEquals
+---------------------------------------------------------------------*/
NPT_Result
NPT_Win32SharedVariable::WaitWhileOrUntilEquals(int value, NPT_Timeout timeout, bool until)
{
    do {
        m_Lock.Lock();
        if (until) {
			if (m_Value == value) break;
		} else {
			if (m_Value != value) break;
		}
		++m_Waiters;
		m_Lock.Unlock();

        NPT_Result result = m_Event.Wait(timeout);
		bool last_waiter = true;
		m_Lock.Lock();
		if (--m_Waiters == 0) {
			m_Event.Reset();
		} else {
			last_waiter = false;
		}
		m_Lock.Unlock();

        if (NPT_FAILED(result)) return result;

		// FIXME: this is suboptimal, but we need it to ensure we don't busy-loop
		if (!last_waiter) {
			Sleep(10);
		}
    } while (true);

    m_Lock.Unlock();

    return NPT_SUCCESS;
}
Пример #2
0
/*----------------------------------------------------------------------
|   NPT_Win32SharedVariable::SetValue
+---------------------------------------------------------------------*/
void
NPT_Win32SharedVariable::SetValue(int value)
{
    m_Lock.Lock();
    if (value != m_Value) {
        m_Value = value;
        m_Event.Signal();
    }
    m_Lock.Unlock();
}
Пример #3
0
/*----------------------------------------------------------------------
|   NPT_Win32Queue::Peek
+---------------------------------------------------------------------*/
NPT_Result
NPT_Win32Queue::Peek(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 = NPT_SUCCESS;
    NPT_List<NPT_QueueItem*>::Iterator head = m_Items.GetFirstItem();
    if (timeout) {
        while (!head) {
            // 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());

            // try again
            head = m_Items.GetFirstItem();
        }
    } else {
        if (!head) result = NPT_ERROR_LIST_EMPTY;
    }

    if (head) item = *head;

    // unlock the mutex
    m_Mutex.Unlock();

    return result;
}
Пример #4
0
/*----------------------------------------------------------------------
|   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;
}
Пример #5
0
/*----------------------------------------------------------------------
|   NPT_Win32Queue::Push
+---------------------------------------------------------------------*/
NPT_Result
NPT_Win32Queue::Push(NPT_QueueItem* item, NPT_Timeout timeout)
{
    // lock the mutex that protects the list
    NPT_CHECK(m_Mutex.Lock());

    // check that we have not exceeded the max
    if (m_MaxItems) {
        while (m_Items.GetItemCount() >= m_MaxItems) {
            // we must wait until some items have been removed

            // reset the condition to indicate that the queue is full
            m_CanPushCondition->Reset();

            // unlock the mutex so that another thread can pop
            m_Mutex.Unlock();

            // wait for the condition to signal that we can push
            NPT_Result result = m_CanPushCondition->Wait(timeout);
            if (NPT_FAILED(result)) return result;

            // relock the mutex so that we can check the list again
            NPT_CHECK(m_Mutex.Lock());
        }
    }

    // add the item to the list
    m_Items.Add(item);

    // wake up the threads waiting to pop
    m_CanPopCondition->Signal();

    // unlock the mutex
    m_Mutex.Unlock();

    return NPT_SUCCESS;
}
Пример #6
0
/*----------------------------------------------------------------------
|   NPT_Win32SharedVariable::WaitWhileEquals
+---------------------------------------------------------------------*/
NPT_Result
NPT_Win32SharedVariable::WaitWhileEquals(int value, NPT_Timeout timeout)
{
    do {
        m_Lock.Lock();
        if (m_Value != value) {
            break;
        }
        m_Lock.Unlock();
        {
             NPT_Result result = m_Event.Wait(timeout);
             if (NPT_FAILED(result)) return result;
        }
    } while (1);

    m_Lock.Unlock();
    
    return NPT_SUCCESS;
}