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