diff options
-rw-r--r-- | chrome/common/ipc_sync_sender.cc | 126 | ||||
-rw-r--r-- | chrome/common/ipc_sync_sender.h | 99 |
2 files changed, 0 insertions, 225 deletions
diff --git a/chrome/common/ipc_sync_sender.cc b/chrome/common/ipc_sync_sender.cc deleted file mode 100644 index eb015a9..0000000 --- a/chrome/common/ipc_sync_sender.cc +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#define WIN32_LEAN_AND_MEAN 1 -#include <windows.h> - -#include "chrome/common/ipc_sync_sender.h" - -#include "chrome/common/ipc_sync_message.h" -#include "base/logging.h" - -namespace IPC { - -SyncSender::SyncSender(HANDLE shutdown_event) : - shutdown_event_(shutdown_event), - reply_deserialize_result_(false), - reply_event_(CreateEvent(NULL, FALSE, FALSE, NULL)), - blocking_event_(CreateEvent(NULL, FALSE, FALSE, NULL)) { - DCHECK(shutdown_event != NULL); -} - -SyncSender::~SyncSender() { - CloseHandle(reply_event_); - CloseHandle(blocking_event_); - DCHECK(deserializers_.empty()); -} - -bool SyncSender::SendSync(IPC::Message* message) { - bool message_is_sync = false; - - message_is_sync = message->is_sync(); - if (message_is_sync) { - IPC::SyncMessage* sync_msg = static_cast<IPC::SyncMessage*>(message); - PendingSyncMsg pending(IPC::SyncMessage::GetMessageId(*sync_msg), - sync_msg->GetReplyDeserializer()); - deserializers_.push(pending); - } - - // Get the derived class to send the message. - bool send_result = SendPrivate(message); - - if (!message_is_sync) - return send_result; - - if (!send_result) { - delete deserializers_.top().deserializer; - deserializers_.pop(); - return false; - } - - do { - // wait for reply - HANDLE objects[] = { reply_event_, blocking_event_, shutdown_event_ }; - DWORD result = WaitForMultipleObjects(3, objects, FALSE, INFINITE); - if (result == WAIT_OBJECT_0 + 2) { - // Process shut down before we can get a reply to a synchronous message. - // Unblock the thread. - return false; - } - - if (result == WAIT_OBJECT_0 + 1) { - // We're waiting for a reply, but the replier is making a synchronous - // request that we must service or else we deadlock. Or in case this - // process supports processing of any synchronous messages while it's - // blocked waiting for a reply (i.e. because it communicates with - // multiple processes). - while (true) { - blocking_messages_lock_.Acquire(); - size_t size = blocking_messages_.size(); - Message* blocking_message; - if (size) { - blocking_message = blocking_messages_.front(); - blocking_messages_.pop(); - } - - blocking_messages_lock_.Release(); - - if (!size) - break; - - OnDispatchMessage(*blocking_message); - delete blocking_message; - } - - // Continue looping until we get the reply to our synchronous message. - } else { - // We got the reply to our synchronous message. - return reply_deserialize_result_; - } - } while (true); -} - -bool SyncSender::OnFilterMessage(const Message& msg) { - if (deserializers_.empty()) - return false; - - if (IPC::SyncMessage::IsMessageReplyTo(msg, deserializers_.top().id)) { - reply_deserialize_result_ = - deserializers_.top().deserializer->SerializeOutputParameters(msg); - delete deserializers_.top().deserializer; - deserializers_.pop(); - SetEvent(reply_event_); - return true; - } - - if (msg.is_sync()) { - // When we're blocked waiting for a reply we have to respond to other - // synchronous messages as they might be blocking our reply. We also don't - // want to block other processes because one is blocked. - - // Create a copy of this message, as it can be deleted from under us - // if there are more than two synchronous messages in parallel. - // (i.e. A->B, B->A, A->B all synchronous) - blocking_messages_lock_.Acquire(); - blocking_messages_.push(new Message(msg)); - blocking_messages_lock_.Release(); - SetEvent(blocking_event_); - return true; - } - - return false; -} - -} // namespace IPC - diff --git a/chrome/common/ipc_sync_sender.h b/chrome/common/ipc_sync_sender.h deleted file mode 100644 index 15a93a6..0000000 --- a/chrome/common/ipc_sync_sender.h +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_COMMON_IPC_SYNC_SENDER_H__ -#define CHROME_COMMON_IPC_SYNC_SENDER_H__ - -#include <windows.h> -#include <string> -#include <stack> -#include <queue> -#include "base/basictypes.h" -#include "chrome/common/ipc_message.h" -#include "chrome/common/lock.h" - -namespace IPC { - -// Classes which send synchronous messages need to derive from this. -// This class is called on two threads. The first is the main thread that does -// the message processing (and which may be blocked waiting for a reply to a -// synchronous message). The second is the IPC thread that does the filtering -// of messages before passing it to the (maybe) blocked main thread. -// -// To use this class: -// 1) Your Send() must pass all messages to SendSync() -// 2) You must implement SendPrivate(), which SendSync() will call internally -// 3) You must be able to filter incoming messages on the IPC thread, and -// pass them on to OnFilterMessage(). -// 4) You must implement OnDispatchMessage, which is what dispatches -// messages on the main thread. - -class SyncSender { - public: - // shutdown_event is an event that can be waited on so that we don't block if - // if the process is shutting down. If it's NULL, then it's not used. - SyncSender(HANDLE shutdown_event); - ~SyncSender(); - - // These are called on the main thread. - - // The derived class's Send should just passthrough to SendSync. - bool SendSync(IPC::Message* message); - - // SendSync will call your implementation's SendPrivate when it comes - // time to send the message on the channel. - virtual bool SendPrivate(IPC::Message* message) = 0; - - // If a message needs to be dispatched immediately because it's blocking our - // reply, this function will be called. - virtual void OnDispatchMessage(const Message& message) = 0; - - // This is called on the IPC thread. Returns true if the message has been - // consumed (i.e. don't do any more processing). - bool OnFilterMessage(const Message& message); - - private: - // When sending a synchronous message, this structure contains an object that - // knows how to deserialize the response. - struct PendingSyncMsg { - PendingSyncMsg(int id, IPC::MessageReplyDeserializer* d) : - id(id), deserializer(d) { } - int id; - IPC::MessageReplyDeserializer* deserializer; - }; - - // Set when we got a reply for a synchronous message that we sent. - HANDLE reply_event_; - - // Set when we got a synchronous message that we must respond to as the - // sender needs its reply before it can reply to our original synchronous - // message. - HANDLE blocking_event_; - - // Copy of shutdown event that we get in constructor. - HANDLE shutdown_event_; - - typedef std::stack<PendingSyncMsg> PendingSyncMessageQueue; - PendingSyncMessageQueue deserializers_; - bool reply_deserialize_result_; - - // If we're waiting on a reply and the caller sends a synchronous message - // that's blocking the reply, this variable is used to pass the intermediate - // "blocking" message between our two threads. We can store multiple - // messages as a process will want to respond to any synchronous message - // while they're blocked (i.e. because they talk to multiple processes). - typedef std::queue<Message*> BlockingMessageQueue; - BlockingMessageQueue blocking_messages_; - - // Above data structure is used on multiple threads, so it need - // synchronization. - Lock blocking_messages_lock_; - - DISALLOW_EVIL_CONSTRUCTORS(SyncSender); -}; - -} // namespace IPC - -#endif // CHROME_COMMON_IPC_SYNC_SENDER_H__ - |