OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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 MOJO_PUBLIC_CPP_BINDINGS_LIB_MULTIPLEX_ROUTER_H_ | |
6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_MULTIPLEX_ROUTER_H_ | |
7 | |
8 #include <deque> | |
9 #include <map> | |
10 | |
11 #include "base/logging.h" | |
12 #include "base/memory/ref_counted_delete_on_message_loop.h" | |
13 #include "base/memory/scoped_ptr.h" | |
14 #include "base/memory/weak_ptr.h" | |
15 #include "base/synchronization/lock.h" | |
16 #include "base/threading/thread_checker.h" | |
17 #include "mojo/public/cpp/bindings/callback.h" | |
18 #include "mojo/public/cpp/bindings/lib/connector.h" | |
19 #include "mojo/public/cpp/bindings/lib/interface_id.h" | |
20 #include "mojo/public/cpp/bindings/lib/message_header_validator.h" | |
21 #include "mojo/public/cpp/bindings/lib/pipe_control_message_handler.h" | |
22 #include "mojo/public/cpp/bindings/lib/pipe_control_message_handler_delegate.h" | |
23 #include "mojo/public/cpp/bindings/lib/pipe_control_message_proxy.h" | |
24 #include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h" | |
25 #include "mojo/public/cpp/environment/environment.h" | |
26 | |
27 namespace mojo { | |
28 namespace internal { | |
29 | |
30 class InterfaceEndpointClient; | |
31 | |
32 // MultiplexRouter supports routing messages for multiple interfaces over a | |
33 // single message pipe. | |
sky
2015/11/19 17:16:27
Please add a more general description of threading
yzshen1
2015/11/19 22:00:40
Done.
| |
34 class MultiplexRouter | |
35 : public MessageReceiver, | |
36 public base::RefCountedDeleteOnMessageLoop<MultiplexRouter>, | |
37 public PipeControlMessageHandlerDelegate { | |
38 public: | |
39 // If |set_interface_id_namespace_bit| is true, the interface IDs generated by | |
40 // this router will have the highest bit set. | |
41 MultiplexRouter( | |
42 bool set_interface_id_namespace_bit, | |
43 ScopedMessagePipeHandle message_pipe, | |
44 const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()); | |
45 | |
46 // --------------------------------------------------------------------------- | |
47 // The following public methods are safe to call from any threads. | |
48 | |
49 // Creates a pair of interface endpoint handles. The method generates a new | |
50 // interface ID and assigns it to the two handles. |local_endpoint| is | |
51 // supposed to be used locally; while |remote_endpoint| is supposed to be sent | |
sky
2015/11/19 17:16:27
You can remove 'supposed' to everywhere you have i
yzshen1
2015/11/19 22:00:40
I see. Thanks!
| |
52 // over the message pipe. | |
53 void CreateEndpointHandlePair(ScopedInterfaceEndpointHandle* local_endpoint, | |
54 ScopedInterfaceEndpointHandle* remote_endpoint); | |
55 | |
56 // Creates an interface endpoint handle from a given interface ID. The handle | |
57 // is supposed to be used locally. | |
58 // Typically, this method is used to (1) create an endpoint handle for the | |
59 // master interface; or (2) create an endpoint handle on receiving an | |
60 // interface ID from the message pipe. | |
61 ScopedInterfaceEndpointHandle CreateLocalEndpointHandle(InterfaceId id); | |
62 | |
63 // Closes an interface endpoint handle. | |
64 void CloseEndpointHandle(InterfaceId id, bool is_local); | |
65 | |
66 // Attaches an client to the specified endpoint to send and receive messages. | |
67 void AttachEndpointClient(const ScopedInterfaceEndpointHandle& handle, | |
68 InterfaceEndpointClient* endpoint_client); | |
69 // Detaches the client attached to the specified endpoint. | |
70 void DetachEndpointClient(const ScopedInterfaceEndpointHandle& handle); | |
71 | |
72 bool SendMessage(const ScopedInterfaceEndpointHandle& handle, | |
73 Message* message); | |
74 | |
75 // Raises an error on the underlying message pipe. It disconnects the pipe | |
76 // and notifies all interfaces running on this pipe. | |
77 void RaiseError(); | |
78 | |
79 // --------------------------------------------------------------------------- | |
80 // The following public methods are supposed to be called on the creating | |
81 // thread. | |
82 | |
83 // Please note that this method shouldn't be called unless it results from an | |
84 // explicit request of the user of bindings (e.g., the user sets an | |
85 // InterfacePtr to null or closes a Binding). | |
86 void CloseMessagePipe() { | |
87 DCHECK(thread_checker_.CalledOnValidThread()); | |
88 connector_.CloseMessagePipe(); | |
89 } | |
90 | |
91 // Extracts the underlying message pipe. | |
92 // | |
93 // TODO(yzshen): For now, users need to make sure there is no one holding on | |
94 // to associated interface endpoint handles at both sides of the message pipe | |
95 // in order to call this method. We need a way to forcefully invalidate | |
96 // associated interface endpoint handles. | |
97 ScopedMessagePipeHandle PassMessagePipe(); | |
98 | |
99 // Blocks the current thread until the first incoming message, or |deadline|. | |
100 bool WaitForIncomingMessage(MojoDeadline deadline) { | |
101 DCHECK(thread_checker_.CalledOnValidThread()); | |
102 return connector_.WaitForIncomingMessage(deadline); | |
103 } | |
104 | |
105 // See Binding for details of pause/resume. | |
106 void PauseIncomingMethodCallProcessing() { | |
107 DCHECK(thread_checker_.CalledOnValidThread()); | |
108 connector_.PauseIncomingMethodCallProcessing(); | |
109 } | |
110 void ResumeIncomingMethodCallProcessing() { | |
111 DCHECK(thread_checker_.CalledOnValidThread()); | |
112 connector_.ResumeIncomingMethodCallProcessing(); | |
113 } | |
114 | |
115 // Sets this object to testing mode. | |
116 // In testing mode, the object doesn't disconnect the underlying message pipe | |
117 // when it receives unexpected or invalid messages. | |
118 void EnableTestingMode(); | |
119 | |
120 // Is the router bound to a message pipe handle? | |
121 bool is_valid() const { | |
122 DCHECK(thread_checker_.CalledOnValidThread()); | |
123 return connector_.is_valid(); | |
124 } | |
125 | |
126 private: | |
127 friend class base::RefCountedDeleteOnMessageLoop<MultiplexRouter>; | |
128 friend class base::DeleteHelper<MultiplexRouter>; | |
129 | |
130 class InterfaceEndpoint; | |
131 struct Task; | |
132 | |
133 ~MultiplexRouter() override; | |
134 | |
135 // MessageReceiver implementation: | |
136 bool Accept(Message* message) override; | |
137 | |
138 // PipeControlMessageHandlerDelegate implementation: | |
139 bool OnPeerAssociatedEndpointClosed(InterfaceId id) override; | |
140 bool OnAssociatedEndpointClosedBeforeSent(InterfaceId id) override; | |
141 | |
142 void OnPipeConnectionError(); | |
143 | |
144 // Processes enqueued tasks (incoming messages and error notifications). | |
145 // If |force_async| is true, it guarantees not to call any | |
146 // InterfaceEndpointClient methods directly. | |
147 // | |
148 // Note: Because calling into InterfaceEndpointClient may lead to destruction | |
149 // of this object, if |force_async| is set to false, the caller needs to hold | |
150 // on to a ref outside of |lock_| before calling this method. | |
151 void ProcessTasks(bool force_async); | |
152 | |
153 // Returns true to indicate that |task| has been processed. Otherwise the task | |
154 // will be added back to the front of the queue. | |
155 // |*force_async| may be set to true to force subsequent tasks being processed | |
156 // in an asynchronous manner. | |
157 bool ProcessNotifyErrorTask(Task* task, bool* force_async); | |
158 bool ProcessIncomingMessageTask(Task* task, bool* force_async); | |
159 | |
160 void LockAndCallProcessTasks(); | |
161 | |
162 void OnEndpointDestructed(InterfaceId id); | |
163 | |
164 void RaiseErrorInNonTestingMode(); | |
165 | |
166 // Whether to set the namespace bit when generating interface IDs. Please see | |
167 // comments of kInterfaceIdNamespaceMask. | |
168 const bool set_interface_id_namespace_bit_; | |
169 | |
170 MessageHeaderValidator header_validator_; | |
171 Connector connector_; | |
172 | |
173 base::ThreadChecker thread_checker_; | |
174 | |
175 // Protects the following members. | |
176 mutable base::Lock lock_; | |
177 PipeControlMessageHandler control_message_handler_; | |
178 PipeControlMessageProxy control_message_proxy_; | |
179 | |
180 // Doesn't own the values. When an InterfaceEndpoint object is destructed, it | |
181 // notifies this object by calling OnEndpointDestructed(). | |
182 std::map<InterfaceId, InterfaceEndpoint*> endpoints_; | |
183 uint32_t next_interface_id_value_; | |
184 | |
185 // Owned objects. | |
186 std::deque<Task*> tasks_; | |
sky
2015/11/19 17:16:27
Can you make this a std::deque<scoped_ptr>?
yzshen1
2015/11/19 22:00:41
I don't think we can do that. IIUC, scoped_ptr mov
sky
2015/11/20 01:00:19
I believe scoped_ptr now supports the move operato
| |
187 | |
188 bool testing_mode_; | |
189 }; | |
sky
2015/11/19 17:16:27
DISALLOW..
yzshen1
2015/11/19 22:00:40
Done.
| |
190 | |
191 } // namespace internal | |
192 } // namespace mojo | |
193 | |
194 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MULTIPLEX_ROUTER_H_ | |
OLD | NEW |