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 |