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; } }
// 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); } } } }