| Index: chrome/common/ipc_sync_channel.h
|
| ===================================================================
|
| --- chrome/common/ipc_sync_channel.h (revision 3707)
|
| +++ chrome/common/ipc_sync_channel.h (working copy)
|
| @@ -7,11 +7,12 @@
|
|
|
| #include <windows.h>
|
| #include <string>
|
| -#include <stack>
|
| -#include <queue>
|
| +#include <deque>
|
| #include "base/basictypes.h"
|
| #include "base/lock.h"
|
| +#include "base/object_watcher.h"
|
| #include "base/ref_counted.h"
|
| +#include "base/scoped_handle.h"
|
| #include "chrome/common/ipc_channel_proxy.h"
|
|
|
| namespace IPC {
|
| @@ -24,17 +25,17 @@
|
| // is more than this object. If the message loop goes away while this object
|
| // is running and it's used to send a message, then it will use the invalid
|
| // message loop pointer to proxy it to the ipc thread.
|
| -class SyncChannel : public ChannelProxy {
|
| +class SyncChannel : public ChannelProxy,
|
| + public base::ObjectWatcher::Delegate {
|
| public:
|
| SyncChannel(const std::wstring& channel_id, Channel::Mode mode,
|
| Channel::Listener* listener, MessageFilter* filter,
|
| MessageLoop* ipc_message_loop, bool create_pipe_now,
|
| - HANDLE shutdown_handle);
|
| + HANDLE shutdown_event);
|
| ~SyncChannel();
|
|
|
| virtual bool Send(Message* message);
|
| virtual bool SendWithTimeout(Message* message, int timeout_ms);
|
| - bool UnblockListener(Message* message);
|
|
|
| // Whether we allow sending messages with no time-out.
|
| void set_sync_messages_with_no_timeout_allowed(bool value) {
|
| @@ -48,74 +49,104 @@
|
| // SyncContext holds the per object data for SyncChannel, so that SyncChannel
|
| // can be deleted while it's being used in a different thread. See
|
| // ChannelProxy::Context for more information.
|
| - class SyncContext : public Context {
|
| + class SyncContext : public Context,
|
| + public base::ObjectWatcher::Delegate {
|
| public:
|
| SyncContext(Channel::Listener* listener,
|
| MessageFilter* filter,
|
| - MessageLoop* ipc_thread);
|
| + MessageLoop* ipc_thread,
|
| + HANDLE shutdown_event);
|
|
|
| ~SyncContext();
|
|
|
| // Adds information about an outgoing sync message to the context so that
|
| - // we know how to deserialize the reply. Returns a handle that's set when
|
| - // the reply has arrived.
|
| - HANDLE Push(IPC::SyncMessage* sync_msg);
|
| + // we know how to deserialize the reply.
|
| + void Push(IPC::SyncMessage* sync_msg);
|
|
|
| - // Returns true if the reply message was deserialized without any errors,
|
| - // or false otherwise.
|
| - bool reply_deserialize_result() { return reply_deserialize_result_; }
|
| + // Cleanly remove the top deserializer (and throw it away). Returns the
|
| + // result of the Send call for that message.
|
| + bool Pop();
|
|
|
| + // Returns an event that's set when the send is complete, timed out or the
|
| + // process shut down.
|
| + HANDLE GetSendDoneEvent();
|
| +
|
| // Returns an event that's set when an incoming message that's not the reply
|
| // needs to get dispatched (by calling SyncContext::DispatchMessages).
|
| - HANDLE blocking_event();
|
| + HANDLE GetDispatchEvent();
|
|
|
| void DispatchMessages();
|
| - void RemoveListener(Channel::Listener* listener);
|
|
|
| // Checks if the given message is blocking the listener thread because of a
|
| // synchronous send. If it is, the thread is unblocked and true is returned.
|
| // Otherwise the function returns false.
|
| - bool UnblockListener(const Message* msg);
|
| + bool TryToUnblockListener(const Message* msg);
|
|
|
| - // Cleanly remove the top deserializer (and throw it away).
|
| - void PopDeserializer(bool close_reply_event);
|
| + // Called on the IPC thread when a sync send that runs a nested message loop
|
| + // times out.
|
| + void OnSendTimeout(int message_id);
|
|
|
| + HANDLE shutdown_event() { return shutdown_event_; }
|
| +
|
| private:
|
| - void OnMessageReceived(const Message& msg);
|
| - void OnChannelError();
|
| + // IPC::ChannelProxy methods that we override.
|
|
|
| + // Called on the listener thread.
|
| + virtual void Clear();
|
| +
|
| + // Called on the IPC thread.
|
| + virtual void OnMessageReceived(const Message& msg);
|
| + virtual void OnChannelError();
|
| + virtual void OnChannelOpened();
|
| + virtual void OnChannelClosed();
|
| +
|
| + // Cancels all pending Send calls.
|
| + void CancelPendingSends();
|
| +
|
| + // ObjectWatcher::Delegate implementation.
|
| + virtual void OnObjectSignaled(HANDLE object);
|
| +
|
| // 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, HANDLE e) :
|
| - id(id), deserializer(d), reply_event(e) { }
|
| + id(id), deserializer(d), done_event(e), send_result(false) { }
|
| int id;
|
| IPC::MessageReplyDeserializer* deserializer;
|
| - HANDLE reply_event;
|
| + HANDLE done_event;
|
| + bool send_result;
|
| };
|
|
|
| - typedef std::stack<PendingSyncMsg> PendingSyncMessageQueue;
|
| + typedef std::deque<PendingSyncMsg> PendingSyncMessageQueue;
|
| PendingSyncMessageQueue deserializers_;
|
| Lock deserializers_lock_;
|
|
|
| - // This can't be a scoped_refptr because it needs to be released on the
|
| - // listener thread.
|
| - ReceivedSyncMsgQueue* received_sync_msgs_;
|
| + scoped_refptr<ReceivedSyncMsgQueue> received_sync_msgs_;
|
|
|
| - bool channel_closed_;
|
| - bool reply_deserialize_result_;
|
| + HANDLE shutdown_event_;
|
| + base::ObjectWatcher shutdown_watcher_;
|
| };
|
|
|
| private:
|
| + // ObjectWatcher::Delegate implementation.
|
| + virtual void OnObjectSignaled(HANDLE object);
|
| +
|
| SyncContext* sync_context() { return reinterpret_cast<SyncContext*>(context()); }
|
|
|
| - // Copy of shutdown event that we get in constructor.
|
| - HANDLE shutdown_event_;
|
| + // Both these functions wait for a reply, timeout or process shutdown. The
|
| + // latter one also runs a nested message loop in the meantime.
|
| + void WaitForReply(HANDLE pump_messages_event);
|
|
|
| - std::stack<HANDLE> pump_messages_events_;
|
| + // Runs a nested message loop until a reply arrives, times out, or the process
|
| + // shuts down.
|
| + void WaitForReplyWithNestedMessageLoop();
|
|
|
| bool sync_messages_with_no_timeout_allowed_;
|
|
|
| + // Used to signal events between the IPC and listener threads.
|
| + base::ObjectWatcher send_done_watcher_;
|
| + base::ObjectWatcher dispatch_watcher_;
|
| +
|
| DISALLOW_EVIL_CONSTRUCTORS(SyncChannel);
|
| };
|
|
|
|
|