Beispiel #1
0
OSCondVarOld::~OSCondVarOld()
{
    Scoped_Lock_Protect(internal_lock_);
    run_state_ = SHUTDOWN;
    if (recycling_list_size_ != allocation_counter_)
    {
        Scoped_Unlock_Protect(internal_lock_);
        SignalAll();
        Sleep(10);
    }
}
void WaitableEvent::Signal()
{
	nbase::NAutoLock locked(&kernel_->lock_);

	if (kernel_->signaled_)
		return;

	if (kernel_->manual_reset_)
	{
		SignalAll();
		kernel_->signaled_ = true;
	}
	else
	{
		// In the case of auto reset, if no waiters were woken, we remain
		// signaled.
		if (!SignalOne())
			kernel_->signaled_ = true;
	}
}
Beispiel #3
0
// Async Read callback
// TODO: Should we add a 'hint' here to let the reader know that we are waiting for
// a certain number of additional bytes? (to prevent unecessary loops)...
void CDSISession::OnReceive(CTCPPacketReader& reader)
{
  DSIHeader hdr;  
  // Technically, we should probably be locking more in here, but we know that there is only one read thread, so 
  // there will never be concurrent calls into this method...
  
  // Ongoing Reply...
  /////////////////////////////////////////////////////
  // TODO: Should we time out after some period...?
  if (m_pOngoingReply) // Do we have a previously-incomplete reply block?
  {
    int err = kNoError;
    // Continue working on the incomplete read...
    int bytesRead = m_pOngoingReply->AppendResponse(reader);    
    if (bytesRead > 0) // All OK
    {
      if (m_pOngoingReply->GetBytesRemaining()) // Not quite done yet...
        return; // Wait some more
    }
    else if(!bytesRead)
    {
      XAFP_LOG(XAFP_LOG_FLAG_ERROR, "DSI Protocol: TCPPacketReader returned zero bytes (expected: %d)", reader.GetBytesLeft());
    }
    else
    {
      XAFP_LOG(XAFP_LOG_FLAG_ERROR, "DSI Protocol: Unable to read response - Error: %d", bytesRead);
      err = kTCPReceiveError;
    }
    
    // We either completed the reply block, or an error occurred. Signal waiting caller
    XAFP_LOG(XAFP_LOG_FLAG_DSI_PROTO, "DSI Protocol: Finished receiving multi-PDU read response (expected: %d, read: %d, pieces: %d)",m_pOngoingReply->GetTotalBytes(), m_pOngoingReply->GetTotalBytes() - m_pOngoingReply->GetBytesRemaining(), m_pOngoingReply->GetPieces());
    m_pOngoingReply->Complete(err); 
    m_pOngoingReply = NULL;
    return;
  }
  
  // 'Standard' Message Block(s) or beginning of a multi-PDU reply
  /////////////////////////////////////////////////////
  while (reader.GetBytesLeft())
  {
    // Read the message header
    int err = reader.Read(&hdr, sizeof(DSIHeader));
    if (err < 0)
    {
      XAFP_LOG(XAFP_LOG_FLAG_ERROR, "DSI Protocol: Unable to read response header - Error: %d", err);
      // TODO: Nothing after this is going to work...figure that out
      return;
    }
    
    translate_header(hdr); // Change from network to host representation
    
    if (!hdr.flags) // This is a server-initiated request (as opposed to a reply to one of our requests)
    {
      switch (hdr.command)
      {
        case DSITickle: // Used by server for 'heartbeat' monitoring
          // TODO: Track time since last notice to detect timeouts
          XAFP_LOG_0(XAFP_LOG_FLAG_DSI_PROTO, "DSI Protocol: Received Server 'Tickle'. Sending reply...");
          SendMessage(DSITickle, GetNewRequestId()); // Send keep-alive reply to server
          break;
        case DSIAttention: // Used by server to notify clients of events
          uint16_t attData;
          // TODO: Implement reconnect handler and heed delay specified by server in AFPUserBytes
          // TODO: Skip unexpected bytes, if present
          // TODO: Retrieve quantum size during login
          if (hdr.totalDataLength > 2)
            XAFP_LOG(XAFP_LOG_FLAG_ERROR,"DSI Protocol: ****Unexpected Size for Attention Data**** (%d bytes)", hdr.totalDataLength);
          reader.Read(&attData, sizeof(uint16_t)); // TODO: Where should we handle read() failures
          attData = ntohs(attData); // Handle byte-ordering
          XAFP_LOG(XAFP_LOG_FLAG_INFO, "DSI Protocol: Received Server Attention. Flags - Shutdown:%s, ServerCrash:%s, Message:%s, NoReconnect:%s",
                   (kShutDownNotifyMask & attData) ? "yes" : "no",
                   (kAllowReconnectMask & attData) ? "yes" : "no",
                   (kMsgNotifyMask & attData) ? "yes" : "no",
                   (kDisconnectNotifyMask & attData) ? "yes" : "no"
                   );
          // TODO: Retrieve the server message when there is one
          OnAttention(attData);
          break;
        case DSICloseSession: // Notification from server that the session will be closed. 
          // Signal all waiting callers and tell them something happened
          XAFP_LOG_0(XAFP_LOG_FLAG_INFO, "DSI Protocol: Server Closed Session. Canceling all pending requests");
          SignalAll(kDSISessionClosed);
          // TODO: Clean-up session (and possibly re-open?)
          break;  
        default:
          XAFP_LOG(XAFP_LOG_FLAG_ERROR,"DSI Protocol: Received unknown request - command: %d", hdr.command);
      }
    }
    else // This is a reply to a previously-sent message
    {
      CDSIRequest* pRequest = NULL;
      
      switch (hdr.command)
      {
        case DSICloseSession: // This should not happen, but handle it anyway...
          XAFP_LOG_0(XAFP_LOG_FLAG_ERROR, "DSI Protocol: Unexpected reply message - CloseSession");        
          // Signal all waiting callers and tell them something happened
          SignalAll(kDSISessionClosed);
          // TODO: Clean-up session (should already be done...)
          break;
        case DSIOpenSession:
        case DSICommand:
        case DSIWrite:
        case DSIGetStatus:
          XAFP_LOG(XAFP_LOG_FLAG_DSI_PROTO, "DSI Protocol: Received Reply - Message:%s, RequestId:%d, result:%d", DSIProtoCommandToString(hdr.command), hdr.requestID, hdr.errorCode);
          // Find the request in our request map
          pRequest = RemoveRequest(hdr.requestID);
          if (pRequest)
          {
            // Tranfer data into caller-supplied buffer, if one was provided
            // If not, they did not expect any data back, just a result code
            // TODO: Make sure all data in the message is read/skipped before moving on, to prevent 
            // clogging-up the pipe...
            pRequest->SaveResponse(reader, hdr.totalDataLength);
            if (pRequest->IsOngoing())
            {
              m_pOngoingReply = pRequest; 
              return; // Wait for more data before signaling requestor...
            }
            // Signal waiting requestor
            // NOTE: This object may self-destruct (or go out of scope) immediately. Do not use the reference again after calling 'Complete'
            pRequest->Complete(hdr.errorCode);
          }
          else
          {
            XAFP_LOG(XAFP_LOG_FLAG_ERROR, "DSI Protocol: Unexpected reply - RequestId: %d", hdr.requestID);
            // TODO: Need a better flush/skip/seek method
            void* p = malloc(hdr.totalDataLength);
            reader.Read(p, hdr.totalDataLength);
            free(p);
          }
          break;
        default:
          // TODO: Skip payload data and try to recover
          XAFP_LOG(XAFP_LOG_FLAG_ERROR, "DSI Protocol: Received unknown reply - command: %d, payload: %d", hdr.command, hdr.totalDataLength);
      }
    }
  }
}