Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Side by Side Diff: mojo/public/cpp/bindings/thread_safe_interface_ptr.h

Issue 2668153003: Mojo C++ Bindings: Eliminate unbound ThreadSafeInterfacePtr (Closed)
Patch Set: format and rebase... Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc ('k') | remoting/host/BUILD.gn » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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_
OLDNEW
« no previous file with comments | « mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc ('k') | remoting/host/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698