void ezPipeChannel_win::OnIOCompleted(IOContext* pContext, DWORD uiBytesTransfered, DWORD uiError) { EZ_ASSERT_DEBUG(m_ThreadId == ezThreadUtils::GetCurrentThreadID(), "Function must be called from worker thread!"); bool bRes = true; if (pContext == &m_InputState.Context) { if (!m_Connected) { if (!ProcessConnection()) return; bool bHasOutput = false; { EZ_LOCK(m_OutputQueueMutex); bHasOutput = !m_OutputQueue.IsEmpty(); } if (bHasOutput && m_OutputState.IsPending == 0) ProcessOutgoingMessages(0); if (m_InputState.IsPending) return; } bRes = ProcessIncomingMessages(uiBytesTransfered); } else { EZ_ASSERT_DEBUG(pContext == &m_OutputState.Context, ""); bRes = ProcessOutgoingMessages(uiBytesTransfered); } if (!bRes && m_PipeHandle != INVALID_HANDLE_VALUE) { InternalDisconnect(); } }
void Channel::OnIOCompleted( Thread::IOContext* context, DWORD bytes_transfered, DWORD error) { bool ok = true; //assert(thread_check_->CalledOnValidThread()); if (context == &input_state_.context) { if (waiting_connect_) { if (!ProcessConnection()) return; // We may have some messages queued up to send... if (!output_queue_.empty() && !output_state_.is_pending) ProcessOutgoingMessages(NULL, 0); if (input_state_.is_pending) return; // else, fall-through and look for incoming messages... } // We don't support recursion through OnMessageReceived yet! assert(!processing_incoming_); processing_incoming_ = true; // Process the new data. if (input_state_.is_pending) { // This is the normal case for everything except the initialization step. input_state_.is_pending = false; if (!bytes_transfered) ok = false; else if (pipe_ != INVALID_HANDLE_VALUE) ok = AsyncReadComplete(bytes_transfered); } else { assert(!bytes_transfered); } // Request more data. if (ok) ok = ProcessIncomingMessages(); processing_incoming_ = false; } else { assert(context == &output_state_.context); ok = ProcessOutgoingMessages(context, bytes_transfered); } if (!ok && INVALID_HANDLE_VALUE != pipe_) { // We don't want to re-enter Close(). Close(); listener()->OnChannelError(); } }
void ezPipeChannel_win::InternalConnect() { if (m_PipeHandle == INVALID_HANDLE_VALUE) return; if (m_Connected) return; #if EZ_ENABLED(EZ_COMPILE_FOR_DEBUG) if (m_ThreadId == 0) m_ThreadId = ezThreadUtils::GetCurrentThreadID(); #endif if (m_Mode == Mode::Server) { ProcessConnection(); } else { m_Connected = true; } if (!m_InputState.IsPending) { OnIOCompleted(&m_InputState.Context, 0, 0); } if (m_Connected) { ProcessOutgoingMessages(0); } m_Events.Broadcast(ezIpcChannelEvent(m_Mode == Mode::Client ? ezIpcChannelEvent::ConnectedToServer : ezIpcChannelEvent::ConnectedToClient, this)); return; }
void ezPipeChannel_win::InternalSend() { if (!m_OutputState.IsPending && m_Connected) { ProcessOutgoingMessages(0); } }
bool Channel::Connect() { //DLOG_IF(WARNING, thread_check_.get()) << "Connect called more than once"; //if (!thread_check_.get()) // thread_check_.reset(new base::ThreadChecker()); if (pipe_ == INVALID_HANDLE_VALUE) return false; thread_->RegisterIOHandler(pipe_, this); // Check to see if there is a client connected to our pipe... if (waiting_connect_) ProcessConnection(); if (!input_state_.is_pending) { // Complete setup asynchronously. By not setting input_state_.is_pending // to true, we indicate to OnIOCompleted that this is the special // initialization signal. thread_->PostTask( std::bind(&Channel::OnIOCompleted, this, &input_state_.context, 0, 0)); } if (!waiting_connect_) ProcessOutgoingMessages(NULL, 0); return true; }
bool Channel::Send(Message* message) { // DCHECK(thread_check_->CalledOnValidThread()); // DVLOG(2) << "sending message @" << message << " on channel @" << this // << " with type " << message->type() // << " (" << output_queue_.size() << " in queue)"; #ifdef IPC_MESSAGE_LOG_ENABLED Logging::GetInstance()->OnSendMessage(message, ""); #endif message->AddRef(); //message->TraceMessageBegin(); output_queue_.push(message); // ensure waiting to write if (!waiting_connect_) { if (!output_state_.is_pending) { if (!ProcessOutgoingMessages(NULL, 0)) return false; } } return true; }