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