| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef CHROME_COMMON_IPC_SYNC_SENDER_H__ | 5 #ifndef CHROME_COMMON_IPC_SYNC_SENDER_H__ |
| 6 #define CHROME_COMMON_IPC_SYNC_SENDER_H__ | 6 #define CHROME_COMMON_IPC_SYNC_SENDER_H__ |
| 7 | 7 |
| 8 #include <windows.h> | 8 #include <windows.h> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <stack> | 10 #include <deque> |
| 11 #include <queue> | |
| 12 #include "base/basictypes.h" | 11 #include "base/basictypes.h" |
| 13 #include "base/lock.h" | 12 #include "base/lock.h" |
| 13 #include "base/object_watcher.h" |
| 14 #include "base/ref_counted.h" | 14 #include "base/ref_counted.h" |
| 15 #include "base/scoped_handle.h" |
| 15 #include "chrome/common/ipc_channel_proxy.h" | 16 #include "chrome/common/ipc_channel_proxy.h" |
| 16 | 17 |
| 17 namespace IPC { | 18 namespace IPC { |
| 18 | 19 |
| 19 class SyncMessage; | 20 class SyncMessage; |
| 20 | 21 |
| 21 // This is similar to IPC::ChannelProxy, with the added feature of supporting | 22 // This is similar to IPC::ChannelProxy, with the added feature of supporting |
| 22 // sending synchronous messages. | 23 // sending synchronous messages. |
| 23 // Note that care must be taken that the lifetime of the ipc_thread argument | 24 // Note that care must be taken that the lifetime of the ipc_thread argument |
| 24 // is more than this object. If the message loop goes away while this object | 25 // is more than this object. If the message loop goes away while this object |
| 25 // is running and it's used to send a message, then it will use the invalid | 26 // is running and it's used to send a message, then it will use the invalid |
| 26 // message loop pointer to proxy it to the ipc thread. | 27 // message loop pointer to proxy it to the ipc thread. |
| 27 class SyncChannel : public ChannelProxy { | 28 class SyncChannel : public ChannelProxy, |
| 29 public base::ObjectWatcher::Delegate { |
| 28 public: | 30 public: |
| 29 SyncChannel(const std::wstring& channel_id, Channel::Mode mode, | 31 SyncChannel(const std::wstring& channel_id, Channel::Mode mode, |
| 30 Channel::Listener* listener, MessageFilter* filter, | 32 Channel::Listener* listener, MessageFilter* filter, |
| 31 MessageLoop* ipc_message_loop, bool create_pipe_now, | 33 MessageLoop* ipc_message_loop, bool create_pipe_now, |
| 32 HANDLE shutdown_handle); | 34 HANDLE shutdown_event); |
| 33 ~SyncChannel(); | 35 ~SyncChannel(); |
| 34 | 36 |
| 35 virtual bool Send(Message* message); | 37 virtual bool Send(Message* message); |
| 36 virtual bool SendWithTimeout(Message* message, int timeout_ms); | 38 virtual bool SendWithTimeout(Message* message, int timeout_ms); |
| 37 bool UnblockListener(Message* message); | |
| 38 | 39 |
| 39 // Whether we allow sending messages with no time-out. | 40 // Whether we allow sending messages with no time-out. |
| 40 void set_sync_messages_with_no_timeout_allowed(bool value) { | 41 void set_sync_messages_with_no_timeout_allowed(bool value) { |
| 41 sync_messages_with_no_timeout_allowed_ = value; | 42 sync_messages_with_no_timeout_allowed_ = value; |
| 42 } | 43 } |
| 43 | 44 |
| 44 protected: | 45 protected: |
| 45 class ReceivedSyncMsgQueue; | 46 class ReceivedSyncMsgQueue; |
| 46 friend class ReceivedSyncMsgQueue; | 47 friend class ReceivedSyncMsgQueue; |
| 47 | 48 |
| 48 // SyncContext holds the per object data for SyncChannel, so that SyncChannel | 49 // SyncContext holds the per object data for SyncChannel, so that SyncChannel |
| 49 // can be deleted while it's being used in a different thread. See | 50 // can be deleted while it's being used in a different thread. See |
| 50 // ChannelProxy::Context for more information. | 51 // ChannelProxy::Context for more information. |
| 51 class SyncContext : public Context { | 52 class SyncContext : public Context, |
| 53 public base::ObjectWatcher::Delegate { |
| 52 public: | 54 public: |
| 53 SyncContext(Channel::Listener* listener, | 55 SyncContext(Channel::Listener* listener, |
| 54 MessageFilter* filter, | 56 MessageFilter* filter, |
| 55 MessageLoop* ipc_thread); | 57 MessageLoop* ipc_thread, |
| 58 HANDLE shutdown_event); |
| 56 | 59 |
| 57 ~SyncContext(); | 60 ~SyncContext(); |
| 58 | 61 |
| 59 // Adds information about an outgoing sync message to the context so that | 62 // Adds information about an outgoing sync message to the context so that |
| 60 // we know how to deserialize the reply. Returns a handle that's set when | 63 // we know how to deserialize the reply. |
| 61 // the reply has arrived. | 64 void Push(IPC::SyncMessage* sync_msg); |
| 62 HANDLE Push(IPC::SyncMessage* sync_msg); | |
| 63 | 65 |
| 64 // Returns true if the reply message was deserialized without any errors, | 66 // Cleanly remove the top deserializer (and throw it away). Returns the |
| 65 // or false otherwise. | 67 // result of the Send call for that message. |
| 66 bool reply_deserialize_result() { return reply_deserialize_result_; } | 68 bool Pop(); |
| 69 |
| 70 // Returns an event that's set when the send is complete, timed out or the |
| 71 // process shut down. |
| 72 HANDLE GetSendDoneEvent(); |
| 67 | 73 |
| 68 // Returns an event that's set when an incoming message that's not the reply | 74 // Returns an event that's set when an incoming message that's not the reply |
| 69 // needs to get dispatched (by calling SyncContext::DispatchMessages). | 75 // needs to get dispatched (by calling SyncContext::DispatchMessages). |
| 70 HANDLE blocking_event(); | 76 HANDLE GetDispatchEvent(); |
| 71 | 77 |
| 72 void DispatchMessages(); | 78 void DispatchMessages(); |
| 73 void RemoveListener(Channel::Listener* listener); | |
| 74 | 79 |
| 75 // Checks if the given message is blocking the listener thread because of a | 80 // Checks if the given message is blocking the listener thread because of a |
| 76 // synchronous send. If it is, the thread is unblocked and true is returned
. | 81 // synchronous send. If it is, the thread is unblocked and true is returned
. |
| 77 // Otherwise the function returns false. | 82 // Otherwise the function returns false. |
| 78 bool UnblockListener(const Message* msg); | 83 bool TryToUnblockListener(const Message* msg); |
| 79 | 84 |
| 80 // Cleanly remove the top deserializer (and throw it away). | 85 // Called on the IPC thread when a sync send that runs a nested message loop |
| 81 void PopDeserializer(bool close_reply_event); | 86 // times out. |
| 87 void OnSendTimeout(int message_id); |
| 88 |
| 89 HANDLE shutdown_event() { return shutdown_event_; } |
| 82 | 90 |
| 83 private: | 91 private: |
| 84 void OnMessageReceived(const Message& msg); | 92 // IPC::ChannelProxy methods that we override. |
| 85 void OnChannelError(); | 93 |
| 94 // Called on the listener thread. |
| 95 virtual void Clear(); |
| 96 |
| 97 // Called on the IPC thread. |
| 98 virtual void OnMessageReceived(const Message& msg); |
| 99 virtual void OnChannelError(); |
| 100 virtual void OnChannelOpened(); |
| 101 virtual void OnChannelClosed(); |
| 102 |
| 103 // Cancels all pending Send calls. |
| 104 void CancelPendingSends(); |
| 105 |
| 106 // ObjectWatcher::Delegate implementation. |
| 107 virtual void OnObjectSignaled(HANDLE object); |
| 86 | 108 |
| 87 // When sending a synchronous message, this structure contains an object tha
t | 109 // When sending a synchronous message, this structure contains an object tha
t |
| 88 // knows how to deserialize the response. | 110 // knows how to deserialize the response. |
| 89 struct PendingSyncMsg { | 111 struct PendingSyncMsg { |
| 90 PendingSyncMsg(int id, IPC::MessageReplyDeserializer* d, HANDLE e) : | 112 PendingSyncMsg(int id, IPC::MessageReplyDeserializer* d, HANDLE e) : |
| 91 id(id), deserializer(d), reply_event(e) { } | 113 id(id), deserializer(d), done_event(e), send_result(false) { } |
| 92 int id; | 114 int id; |
| 93 IPC::MessageReplyDeserializer* deserializer; | 115 IPC::MessageReplyDeserializer* deserializer; |
| 94 HANDLE reply_event; | 116 HANDLE done_event; |
| 117 bool send_result; |
| 95 }; | 118 }; |
| 96 | 119 |
| 97 typedef std::stack<PendingSyncMsg> PendingSyncMessageQueue; | 120 typedef std::deque<PendingSyncMsg> PendingSyncMessageQueue; |
| 98 PendingSyncMessageQueue deserializers_; | 121 PendingSyncMessageQueue deserializers_; |
| 99 Lock deserializers_lock_; | 122 Lock deserializers_lock_; |
| 100 | 123 |
| 101 // This can't be a scoped_refptr because it needs to be released on the | 124 scoped_refptr<ReceivedSyncMsgQueue> received_sync_msgs_; |
| 102 // listener thread. | |
| 103 ReceivedSyncMsgQueue* received_sync_msgs_; | |
| 104 | 125 |
| 105 bool channel_closed_; | 126 HANDLE shutdown_event_; |
| 106 bool reply_deserialize_result_; | 127 base::ObjectWatcher shutdown_watcher_; |
| 107 }; | 128 }; |
| 108 | 129 |
| 109 private: | 130 private: |
| 131 // ObjectWatcher::Delegate implementation. |
| 132 virtual void OnObjectSignaled(HANDLE object); |
| 133 |
| 110 SyncContext* sync_context() { return reinterpret_cast<SyncContext*>(context())
; } | 134 SyncContext* sync_context() { return reinterpret_cast<SyncContext*>(context())
; } |
| 111 | 135 |
| 112 // Copy of shutdown event that we get in constructor. | 136 // Both these functions wait for a reply, timeout or process shutdown. The |
| 113 HANDLE shutdown_event_; | 137 // latter one also runs a nested message loop in the meantime. |
| 138 void WaitForReply(HANDLE pump_messages_event); |
| 114 | 139 |
| 115 std::stack<HANDLE> pump_messages_events_; | 140 // Runs a nested message loop until a reply arrives, times out, or the process |
| 141 // shuts down. |
| 142 void WaitForReplyWithNestedMessageLoop(); |
| 116 | 143 |
| 117 bool sync_messages_with_no_timeout_allowed_; | 144 bool sync_messages_with_no_timeout_allowed_; |
| 118 | 145 |
| 146 // Used to signal events between the IPC and listener threads. |
| 147 base::ObjectWatcher send_done_watcher_; |
| 148 base::ObjectWatcher dispatch_watcher_; |
| 149 |
| 119 DISALLOW_EVIL_CONSTRUCTORS(SyncChannel); | 150 DISALLOW_EVIL_CONSTRUCTORS(SyncChannel); |
| 120 }; | 151 }; |
| 121 | 152 |
| 122 } // namespace IPC | 153 } // namespace IPC |
| 123 | 154 |
| 124 #endif // CHROME_COMMON_IPC_SYNC_SENDER_H__ | 155 #endif // CHROME_COMMON_IPC_SYNC_SENDER_H__ |
| 125 | 156 |
| OLD | NEW |