OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 MOJO_PUBLIC_CPP_BINDINGS_THREAD_SAFE_INTERFACE_PTR_H_ | 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_THREAD_SAFE_INTERFACE_PTR_H_ |
6 #define MOJO_PUBLIC_CPP_BINDINGS_THREAD_SAFE_INTERFACE_PTR_H_ | 6 #define MOJO_PUBLIC_CPP_BINDINGS_THREAD_SAFE_INTERFACE_PTR_H_ |
7 | 7 |
8 #include <memory> | 8 #include <memory> |
9 | 9 |
10 #include "base/macros.h" | 10 #include "base/macros.h" |
11 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
12 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
13 #include "base/task_runner.h" | 13 #include "base/task_runner.h" |
14 #include "base/threading/thread_task_runner_handle.h" | 14 #include "base/threading/thread_task_runner_handle.h" |
15 #include "mojo/public/cpp/bindings/associated_interface_ptr.h" | 15 #include "mojo/public/cpp/bindings/associated_interface_ptr.h" |
16 #include "mojo/public/cpp/bindings/interface_ptr.h" | 16 #include "mojo/public/cpp/bindings/interface_ptr.h" |
17 #include "mojo/public/cpp/bindings/message.h" | 17 #include "mojo/public/cpp/bindings/message.h" |
18 | 18 |
19 namespace mojo { | 19 namespace mojo { |
20 | 20 |
21 struct ThreadSafeInterfacePtrDeleter; | 21 // Instances of this class may be used from any thread to serialize |Interface| |
22 | 22 // messages and forward them elsewhere. In general you should use one of the |
23 // ThreadSafeInterfacePtr and ThreadSafeAssociatedInterfacePtr are versions of | 23 // ThreadSafeInterfacePtrBase helper aliases defined below, but this type may be |
24 // InterfacePtr and AssociatedInterfacePtr that let callers invoke | 24 // useful if you need/want to manually manage the lifetime of the underlying |
25 // interface methods from any threads. Callbacks are received on the thread that | 25 // proxy object which will be used to ultimately send messages. |
26 // performed the interface call. | 26 template <typename Interface> |
27 // | 27 class ThreadSafeForwarder : public MessageReceiverWithResponder { |
28 // To create a ThreadSafeInterfacePtr/ThreadSafeAssociatedInterfacePtr, first | |
29 // create a regular InterfacePtr/AssociatedInterfacePtr that | |
30 // you then provide to ThreadSafeInterfacePtr/AssociatedInterfacePtr::Create. | |
31 // You can then call methods on the | |
32 // ThreadSafeInterfacePtr/AssociatedInterfacePtr instance from any thread. | |
33 // | |
34 // Ex for ThreadSafeInterfacePtr: | |
35 // frob::FrobinatorPtr frobinator; | |
36 // frob::FrobinatorImpl impl(MakeRequest(&frobinator)); | |
37 // scoped_refptr<frob::ThreadSafeFrobinatorPtr> thread_safe_frobinator = | |
38 // frob::ThreadSafeFrobinatorPtr::Create(std::move(frobinator)); | |
39 // (*thread_safe_frobinator)->FrobinateToTheMax(); | |
40 // | |
41 // An alternate way is to create the ThreadSafeInterfacePtr unbound (not | |
42 // associated with an InterfacePtr) and call Bind() at a later time when the | |
43 // InterfacePtr becomes available. Note that you shouldn't call any interface | |
44 // methods on the ThreadSafeInterfacePtr before it is bound. | |
45 | |
46 template <typename Interface, template <typename> class InterfacePtrType> | |
47 class ThreadSafeInterfacePtrBase | |
48 : public MessageReceiverWithResponder, | |
49 public base::RefCountedThreadSafe< | |
50 ThreadSafeInterfacePtrBase<Interface, InterfacePtrType>, | |
51 ThreadSafeInterfacePtrDeleter> { | |
52 public: | 28 public: |
53 using ProxyType = typename Interface::Proxy_; | 29 using ProxyType = typename Interface::Proxy_; |
| 30 using ForwardMessageCallback = base::Callback<void(Message)>; |
| 31 using ForwardMessageWithResponderCallback = |
| 32 base::Callback<void(Message, std::unique_ptr<MessageReceiver>)>; |
54 | 33 |
55 static scoped_refptr<ThreadSafeInterfacePtrBase<Interface, InterfacePtrType>> | 34 // Constructs a ThreadSafeForwarder through which Messages are forwarded to |
56 Create(InterfacePtrType<Interface> interface_ptr) { | 35 // |forward| or |forward_with_responder| by posting to |task_runner|. |
57 scoped_refptr<ThreadSafeInterfacePtrBase> ptr( | 36 // |
58 new ThreadSafeInterfacePtrBase()); | 37 // Any message sent through this forwarding interface will dispatch its reply, |
59 return ptr->Bind(std::move(interface_ptr)) ? ptr : nullptr; | 38 // if any, back to the thread which called the corresponding interface method. |
60 } | 39 ThreadSafeForwarder( |
| 40 const scoped_refptr<base::SequencedTaskRunner>& task_runner, |
| 41 const ForwardMessageCallback& forward, |
| 42 const ForwardMessageWithResponderCallback& forward_with_responder) |
| 43 : proxy_(this), |
| 44 task_runner_(task_runner), |
| 45 forward_(forward), |
| 46 forward_with_responder_(forward_with_responder) {} |
61 | 47 |
62 // Creates a ThreadSafeInterfacePtrBase with no associated InterfacePtr. | 48 ~ThreadSafeForwarder() override {} |
63 // Call Bind() with the InterfacePtr once available, which must be called on | |
64 // the |bind_task_runner|. | |
65 // Providing the TaskRunner here allows you to post a task to | |
66 // |bind_task_runner| to do the bind and then immediately start calling | |
67 // methods on the returned interface. | |
68 static scoped_refptr<ThreadSafeInterfacePtrBase<Interface, InterfacePtrType>> | |
69 CreateUnbound( | |
70 const scoped_refptr<base::SingleThreadTaskRunner>& bind_task_runner) { | |
71 scoped_refptr<ThreadSafeInterfacePtrBase<Interface, InterfacePtrType>> ptr = | |
72 new ThreadSafeInterfacePtrBase(); | |
73 ptr->interface_ptr_task_runner_ = bind_task_runner; | |
74 return ptr; | |
75 } | |
76 | 49 |
77 // Binds a ThreadSafeInterfacePtrBase previously created with CreateUnbound(). | 50 ProxyType& proxy() { return proxy_; } |
78 // This must be called on the thread that |interface_ptr| should be used. | |
79 // If created with CreateUnbound() that thread should be the same as the one | |
80 // provided at creation time. | |
81 bool Bind(InterfacePtrType<Interface> interface_ptr) { | |
82 DCHECK(!interface_ptr_task_runner_ || | |
83 interface_ptr_task_runner_ == base::ThreadTaskRunnerHandle::Get()); | |
84 if (!interface_ptr.is_bound()) { | |
85 LOG(ERROR) << "Attempting to bind a ThreadSafe[Associated]InterfacePtr " | |
86 "from an unbound InterfacePtr."; | |
87 return false; | |
88 } | |
89 interface_ptr_ = std::move(interface_ptr); | |
90 interface_ptr_task_runner_ = base::ThreadTaskRunnerHandle::Get(); | |
91 return true; | |
92 } | |
93 | |
94 ~ThreadSafeInterfacePtrBase() override {} | |
95 | |
96 Interface* get() { return &proxy_; } | |
97 Interface* operator->() { return get(); } | |
98 Interface& operator*() { return *get(); } | |
99 | 51 |
100 private: | 52 private: |
101 friend class base::RefCountedThreadSafe< | |
102 ThreadSafeInterfacePtrBase<Interface, InterfacePtrType>>; | |
103 friend struct ThreadSafeInterfacePtrDeleter; | |
104 | |
105 ThreadSafeInterfacePtrBase() : proxy_(this), weak_ptr_factory_(this) {} | |
106 | |
107 void DeleteOnCorrectThread() const { | |
108 if (interface_ptr_task_runner_ && | |
109 !interface_ptr_task_runner_->BelongsToCurrentThread() && | |
110 interface_ptr_task_runner_->DeleteSoon(FROM_HERE, this)) { | |
111 return; | |
112 } | |
113 delete this; | |
114 } | |
115 | |
116 // MessageReceiverWithResponder implementation: | 53 // MessageReceiverWithResponder implementation: |
117 bool Accept(Message* message) override { | 54 bool Accept(Message* message) override { |
118 interface_ptr_task_runner_->PostTask( | 55 task_runner_->PostTask(FROM_HERE, |
119 FROM_HERE, | 56 base::Bind(forward_, base::Passed(message))); |
120 base::Bind(&ThreadSafeInterfacePtrBase::AcceptOnInterfacePtrThread, | |
121 weak_ptr_factory_.GetWeakPtr(), | |
122 base::Passed(std::move(*message)))); | |
123 return true; | 57 return true; |
124 } | 58 } |
125 | 59 |
126 bool AcceptWithResponder(Message* message, | 60 bool AcceptWithResponder(Message* message, |
127 MessageReceiver* responder) override { | 61 MessageReceiver* response_receiver) override { |
128 auto forward_responder = base::MakeUnique<ForwardToCallingThread>( | 62 auto responder = base::MakeUnique<ForwardToCallingThread>( |
129 base::WrapUnique(responder)); | 63 base::WrapUnique(response_receiver)); |
130 interface_ptr_task_runner_->PostTask( | 64 task_runner_->PostTask( |
131 FROM_HERE, base::Bind(&ThreadSafeInterfacePtrBase:: | 65 FROM_HERE, base::Bind(forward_with_responder_, base::Passed(message), |
132 AcceptWithResponderOnInterfacePtrThread, | 66 base::Passed(&responder))); |
133 weak_ptr_factory_.GetWeakPtr(), | |
134 base::Passed(std::move(*message)), | |
135 base::Passed(std::move(forward_responder)))); | |
136 return true; | 67 return true; |
137 } | 68 } |
138 | 69 |
139 void AcceptOnInterfacePtrThread(Message message) { | |
140 interface_ptr_.internal_state()->ForwardMessage(std::move(message)); | |
141 } | |
142 void AcceptWithResponderOnInterfacePtrThread( | |
143 Message message, | |
144 std::unique_ptr<MessageReceiver> responder) { | |
145 interface_ptr_.internal_state()->ForwardMessageWithResponder( | |
146 std::move(message), std::move(responder)); | |
147 } | |
148 | |
149 class ForwardToCallingThread : public MessageReceiver { | 70 class ForwardToCallingThread : public MessageReceiver { |
150 public: | 71 public: |
151 explicit ForwardToCallingThread(std::unique_ptr<MessageReceiver> responder) | 72 explicit ForwardToCallingThread(std::unique_ptr<MessageReceiver> responder) |
152 : responder_(std::move(responder)), | 73 : responder_(std::move(responder)), |
153 caller_task_runner_(base::ThreadTaskRunnerHandle::Get()) { | 74 caller_task_runner_(base::ThreadTaskRunnerHandle::Get()) { |
154 } | 75 } |
155 | 76 |
156 private: | 77 private: |
157 bool Accept(Message* message) { | 78 bool Accept(Message* message) { |
158 // The current instance will be deleted when this method returns, so we | 79 // The current instance will be deleted when this method returns, so we |
159 // have to relinquish the responder's ownership so it does not get | 80 // have to relinquish the responder's ownership so it does not get |
160 // deleted. | 81 // deleted. |
161 caller_task_runner_->PostTask(FROM_HERE, | 82 caller_task_runner_->PostTask(FROM_HERE, |
162 base::Bind(&ForwardToCallingThread::CallAcceptAndDeleteResponder, | 83 base::Bind(&ForwardToCallingThread::CallAcceptAndDeleteResponder, |
163 base::Passed(std::move(responder_)), | 84 base::Passed(std::move(responder_)), |
164 base::Passed(std::move(*message)))); | 85 base::Passed(std::move(*message)))); |
165 return true; | 86 return true; |
166 } | 87 } |
167 | 88 |
168 static void CallAcceptAndDeleteResponder( | 89 static void CallAcceptAndDeleteResponder( |
169 std::unique_ptr<MessageReceiver> responder, | 90 std::unique_ptr<MessageReceiver> responder, |
170 Message message) { | 91 Message message) { |
171 ignore_result(responder->Accept(&message)); | 92 ignore_result(responder->Accept(&message)); |
172 } | 93 } |
173 | 94 |
174 std::unique_ptr<MessageReceiver> responder_; | 95 std::unique_ptr<MessageReceiver> responder_; |
175 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_; | 96 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_; |
176 }; | 97 }; |
177 | 98 |
178 scoped_refptr<base::SingleThreadTaskRunner> interface_ptr_task_runner_; | |
179 ProxyType proxy_; | 99 ProxyType proxy_; |
180 InterfacePtrType<Interface> interface_ptr_; | 100 const scoped_refptr<base::SequencedTaskRunner> task_runner_; |
181 base::WeakPtrFactory<ThreadSafeInterfacePtrBase> weak_ptr_factory_; | 101 const ForwardMessageCallback forward_; |
| 102 const ForwardMessageWithResponderCallback forward_with_responder_; |
| 103 |
| 104 DISALLOW_COPY_AND_ASSIGN(ThreadSafeForwarder); |
182 }; | 105 }; |
183 | 106 |
184 struct ThreadSafeInterfacePtrDeleter { | 107 template <typename InterfacePtrType> |
185 template <typename Interface, template <typename> class InterfacePtrType> | 108 class ThreadSafeInterfacePtrBase |
186 static void Destruct( | 109 : public base::RefCountedThreadSafe< |
187 const ThreadSafeInterfacePtrBase<Interface, InterfacePtrType>* | 110 ThreadSafeInterfacePtrBase<InterfacePtrType>> { |
188 interface_ptr) { | 111 public: |
189 interface_ptr->DeleteOnCorrectThread(); | 112 using InterfaceType = typename InterfacePtrType::InterfaceType; |
| 113 using PtrInfoType = typename InterfacePtrType::PtrInfoType; |
| 114 |
| 115 explicit ThreadSafeInterfacePtrBase( |
| 116 std::unique_ptr<ThreadSafeForwarder<InterfaceType>> forwarder) |
| 117 : forwarder_(std::move(forwarder)) {} |
| 118 |
| 119 // Creates a ThreadSafeInterfacePtrBase wrapping an underlying non-thread-safe |
| 120 // InterfacePtrType which is bound to the calling thread. All messages sent |
| 121 // via this thread-safe proxy will internally be sent by first posting to this |
| 122 // (the calling) thread's TaskRunner. |
| 123 static scoped_refptr<ThreadSafeInterfacePtrBase> Create( |
| 124 InterfacePtrType interface_ptr) { |
| 125 scoped_refptr<PtrWrapper> wrapper = |
| 126 new PtrWrapper(std::move(interface_ptr)); |
| 127 return new ThreadSafeInterfacePtrBase(wrapper->CreateForwarder()); |
190 } | 128 } |
| 129 |
| 130 // Creates a ThreadSafeInterfacePtrBase which binds the underlying |
| 131 // non-thread-safe InterfacePtrType on the specified TaskRunner. All messages |
| 132 // sent via this thread-safe proxy will internally be sent by first posting to |
| 133 // that TaskRunner. |
| 134 static scoped_refptr<ThreadSafeInterfacePtrBase> Create( |
| 135 PtrInfoType ptr_info, |
| 136 const scoped_refptr<base::SingleThreadTaskRunner>& bind_task_runner) { |
| 137 scoped_refptr<PtrWrapper> wrapper = new PtrWrapper(bind_task_runner); |
| 138 wrapper->BindOnTaskRunner(std::move(ptr_info)); |
| 139 return new ThreadSafeInterfacePtrBase(wrapper->CreateForwarder()); |
| 140 } |
| 141 |
| 142 InterfaceType* get() { return &forwarder_->proxy(); } |
| 143 InterfaceType* operator->() { return get(); } |
| 144 InterfaceType& operator*() { return *get(); } |
| 145 |
| 146 private: |
| 147 friend class base::RefCountedThreadSafe< |
| 148 ThreadSafeInterfacePtrBase<InterfacePtrType>>; |
| 149 |
| 150 struct PtrWrapperDeleter; |
| 151 |
| 152 // Helper class which owns an |InterfacePtrType| instance on an appropriate |
| 153 // thread. This is kept alive as long its bound within some |
| 154 // ThreadSafeForwarder's callbacks. |
| 155 class PtrWrapper |
| 156 : public base::RefCountedThreadSafe<PtrWrapper, PtrWrapperDeleter> { |
| 157 public: |
| 158 explicit PtrWrapper(InterfacePtrType ptr) |
| 159 : PtrWrapper(base::ThreadTaskRunnerHandle::Get()) { |
| 160 ptr_ = std::move(ptr); |
| 161 } |
| 162 |
| 163 explicit PtrWrapper( |
| 164 const scoped_refptr<base::SequencedTaskRunner>& task_runner) |
| 165 : task_runner_(task_runner) {} |
| 166 |
| 167 void BindOnTaskRunner(PtrInfoType ptr_info) { |
| 168 task_runner_->PostTask(FROM_HERE, base::Bind(&PtrWrapper::Bind, this, |
| 169 base::Passed(&ptr_info))); |
| 170 } |
| 171 |
| 172 std::unique_ptr<ThreadSafeForwarder<InterfaceType>> CreateForwarder() { |
| 173 return base::MakeUnique<ThreadSafeForwarder<InterfaceType>>( |
| 174 task_runner_, base::Bind(&PtrWrapper::Accept, this), |
| 175 base::Bind(&PtrWrapper::AcceptWithResponder, this)); |
| 176 } |
| 177 |
| 178 private: |
| 179 friend struct PtrWrapperDeleter; |
| 180 |
| 181 ~PtrWrapper() {} |
| 182 |
| 183 void Bind(PtrInfoType ptr_info) { |
| 184 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 185 ptr_.Bind(std::move(ptr_info)); |
| 186 } |
| 187 |
| 188 void Accept(Message message) { |
| 189 ptr_.internal_state()->ForwardMessage(std::move(message)); |
| 190 } |
| 191 |
| 192 void AcceptWithResponder(Message message, |
| 193 std::unique_ptr<MessageReceiver> responder) { |
| 194 ptr_.internal_state()->ForwardMessageWithResponder(std::move(message), |
| 195 std::move(responder)); |
| 196 } |
| 197 |
| 198 void DeleteOnCorrectThread() const { |
| 199 if (!task_runner_->RunsTasksOnCurrentThread()) { |
| 200 // NOTE: This is only called when there are no more references to |
| 201 // |this|, so binding it unretained is both safe and necessary. |
| 202 task_runner_->PostTask(FROM_HERE, |
| 203 base::Bind(&PtrWrapper::DeleteOnCorrectThread, |
| 204 base::Unretained(this))); |
| 205 } else { |
| 206 delete this; |
| 207 } |
| 208 } |
| 209 |
| 210 InterfacePtrType ptr_; |
| 211 const scoped_refptr<base::SequencedTaskRunner> task_runner_; |
| 212 |
| 213 DISALLOW_COPY_AND_ASSIGN(PtrWrapper); |
| 214 }; |
| 215 |
| 216 struct PtrWrapperDeleter { |
| 217 static void Destruct(const PtrWrapper* interface_ptr) { |
| 218 interface_ptr->DeleteOnCorrectThread(); |
| 219 } |
| 220 }; |
| 221 |
| 222 ~ThreadSafeInterfacePtrBase() {} |
| 223 |
| 224 const std::unique_ptr<ThreadSafeForwarder<InterfaceType>> forwarder_; |
| 225 |
| 226 DISALLOW_COPY_AND_ASSIGN(ThreadSafeInterfacePtrBase); |
191 }; | 227 }; |
192 | 228 |
193 template <typename Interface> | 229 template <typename Interface> |
194 using ThreadSafeAssociatedInterfacePtr = | 230 using ThreadSafeAssociatedInterfacePtr = |
195 ThreadSafeInterfacePtrBase<Interface, AssociatedInterfacePtr>; | 231 ThreadSafeInterfacePtrBase<AssociatedInterfacePtr<Interface>>; |
196 | 232 |
197 template <typename Interface> | 233 template <typename Interface> |
198 using ThreadSafeInterfacePtr = | 234 using ThreadSafeInterfacePtr = |
199 ThreadSafeInterfacePtrBase<Interface, InterfacePtr>; | 235 ThreadSafeInterfacePtrBase<InterfacePtr<Interface>>; |
200 | 236 |
201 } // namespace mojo | 237 } // namespace mojo |
202 | 238 |
203 #endif // MOJO_PUBLIC_CPP_BINDINGS_THREAD_SAFE_INTERFACE_PTR_H_ | 239 #endif // MOJO_PUBLIC_CPP_BINDINGS_THREAD_SAFE_INTERFACE_PTR_H_ |
OLD | NEW |