Beispiel #1
0
HRESULT
CAsyncIo::BeginFlush()
{
    
    {
        CAutoLock lock(&m_csLists);

        
        
        
        
        m_bFlushing = TRUE;

        CAsyncRequest * preq;
        while(preq = GetWorkItem()) {
            preq->Cancel();
            PutDoneItem(preq);
        }

        
        if (m_cItemsOut > 0) {

            
            ASSERT(!m_bWaiting);

            
            
            
            m_bWaiting = TRUE;
        } else {
            

            
            
            
            
            m_evDone.Set();
            return S_OK;
        }
    }

    ASSERT(m_bWaiting);

    
    for (;;) {
        m_evAllDone.Wait();
        {
            
            CAutoLock lock(&m_csLists);

            if (m_cItemsOut == 0) {

                
                
                m_bWaiting = FALSE;

                
                
                
                
                m_evDone.Set();

                return S_OK;
            }
        }
    }
}
// cancel all items on the worklist onto the done list
// and refuse further requests or further WaitForNext calls
// until the end flush
//
// WaitForNext must return with NULL only if there are no successful requests.
// So Flush does the following:
// 1. set m_bFlushing ensures no more requests succeed
// 2. move all items from work list to the done list.
// 3. If there are any outstanding requests, then we need to release the
//    critsec to allow them to complete. The m_bWaiting as well as ensuring
//    that we are signalled when they are all done is also used to indicate
//    to WaitForNext that it should continue to block.
// 4. Once all outstanding requests are complete, we force m_evDone set and
//    m_bFlushing set and m_bWaiting false. This ensures that WaitForNext will
//    not block when the done list is empty.
HRESULT
  CAsyncIo::BeginFlush()
{
  // hold the lock while emptying the work list
  {
    CAutoLock lock(&m_csLists);

    // prevent further requests being queued.
    // Also WaitForNext will refuse to block if this is set
    // unless m_bWaiting is also set which it will be when we release
    // the critsec if there are any outstanding).
    m_bFlushing = TRUE;

    CAsyncRequest * preq;
    while((preq = GetWorkItem()) != 0)
    {
      preq->Cancel();
      PutDoneItem(preq);
    }

    // now wait for any outstanding requests to complete
    if(m_cItemsOut > 0)
    {
      // can be only one person waiting
      ASSERT(!m_bWaiting);

      // this tells the completion routine that we need to be
      // signalled via m_evAllDone when all outstanding items are
      // done. It also tells WaitForNext to continue blocking.
      m_bWaiting = TRUE;
    }
    else
    {
      // all done

      // force m_evDone set so that even if list is empty,
      // WaitForNext will not block
      // don't do this until we are sure that all
      // requests are on the done list.
      m_evDone.Set();
      return S_OK;
    }
  }

  ASSERT(m_bWaiting);

  // wait without holding critsec
  for(;;)
  {
    m_evAllDone.Wait();
    {
      // hold critsec to check
      CAutoLock lock(&m_csLists);

      if(m_cItemsOut == 0)
      {
        // now we are sure that all outstanding requests are on
        // the done list and no more will be accepted
        m_bWaiting = FALSE;

        // force m_evDone set so that even if list is empty,
        // WaitForNext will not block
        // don't do this until we are sure that all
        // requests are on the done list.
        m_evDone.Set();

        return S_OK;
      }
    }
  }
}