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/sequenced_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 struct ThreadSafeInterfacePtrDeleter; |
22 | 22 |
23 // ThreadSafeInterfacePtr and ThreadSafeAssociatedInterfacePtr are versions of | 23 // ThreadSafeInterfacePtr and ThreadSafeAssociatedInterfacePtr are versions of |
24 // InterfacePtr and AssociatedInterfacePtr that let callers invoke | 24 // InterfacePtr and AssociatedInterfacePtr that let callers invoke |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 } | 60 } |
61 | 61 |
62 // Creates a ThreadSafeInterfacePtrBase with no associated InterfacePtr. | 62 // Creates a ThreadSafeInterfacePtrBase with no associated InterfacePtr. |
63 // Call Bind() with the InterfacePtr once available, which must be called on | 63 // Call Bind() with the InterfacePtr once available, which must be called on |
64 // the |bind_task_runner|. | 64 // the |bind_task_runner|. |
65 // Providing the TaskRunner here allows you to post a task to | 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 | 66 // |bind_task_runner| to do the bind and then immediately start calling |
67 // methods on the returned interface. | 67 // methods on the returned interface. |
68 static scoped_refptr<ThreadSafeInterfacePtrBase<Interface, InterfacePtrType>> | 68 static scoped_refptr<ThreadSafeInterfacePtrBase<Interface, InterfacePtrType>> |
69 CreateUnbound( | 69 CreateUnbound( |
70 const scoped_refptr<base::SingleThreadTaskRunner>& bind_task_runner) { | 70 const scoped_refptr<base::SequencedTaskRunner>& bind_task_runner) { |
71 scoped_refptr<ThreadSafeInterfacePtrBase<Interface, InterfacePtrType>> ptr = | 71 scoped_refptr<ThreadSafeInterfacePtrBase<Interface, InterfacePtrType>> ptr = |
72 new ThreadSafeInterfacePtrBase(); | 72 new ThreadSafeInterfacePtrBase(); |
73 ptr->interface_ptr_task_runner_ = bind_task_runner; | 73 ptr->interface_ptr_task_runner_ = bind_task_runner; |
74 return ptr; | 74 return ptr; |
75 } | 75 } |
76 | 76 |
77 // Binds a ThreadSafeInterfacePtrBase previously created with CreateUnbound(). | 77 // Binds a ThreadSafeInterfacePtrBase previously created with CreateUnbound(). |
78 // This must be called on the thread that |interface_ptr| should be used. | 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 | 79 // If created with CreateUnbound() that thread should be the same as the one |
80 // provided at creation time. | 80 // provided at creation time. |
81 bool Bind(InterfacePtrType<Interface> interface_ptr) { | 81 bool Bind(InterfacePtrType<Interface> interface_ptr) { |
82 DCHECK(!interface_ptr_task_runner_ || | 82 DCHECK(!interface_ptr_task_runner_ || |
83 interface_ptr_task_runner_ == base::ThreadTaskRunnerHandle::Get()); | 83 interface_ptr_task_runner_ == |
| 84 base::SequencedTaskRunnerHandle::Get()); |
84 if (!interface_ptr.is_bound()) { | 85 if (!interface_ptr.is_bound()) { |
85 LOG(ERROR) << "Attempting to bind a ThreadSafe[Associated]InterfacePtr " | 86 LOG(ERROR) << "Attempting to bind a ThreadSafe[Associated]InterfacePtr " |
86 "from an unbound InterfacePtr."; | 87 "from an unbound InterfacePtr."; |
87 return false; | 88 return false; |
88 } | 89 } |
89 interface_ptr_ = std::move(interface_ptr); | 90 interface_ptr_ = std::move(interface_ptr); |
90 interface_ptr_task_runner_ = base::ThreadTaskRunnerHandle::Get(); | 91 interface_ptr_task_runner_ = base::SequencedTaskRunnerHandle::Get(); |
91 return true; | 92 return true; |
92 } | 93 } |
93 | 94 |
94 ~ThreadSafeInterfacePtrBase() override {} | 95 ~ThreadSafeInterfacePtrBase() override {} |
95 | 96 |
96 Interface* get() { return &proxy_; } | 97 Interface* get() { return &proxy_; } |
97 Interface* operator->() { return get(); } | 98 Interface* operator->() { return get(); } |
98 Interface& operator*() { return *get(); } | 99 Interface& operator*() { return *get(); } |
99 | 100 |
100 private: | 101 private: |
101 friend class base::RefCountedThreadSafe< | 102 friend class base::RefCountedThreadSafe< |
102 ThreadSafeInterfacePtrBase<Interface, InterfacePtrType>>; | 103 ThreadSafeInterfacePtrBase<Interface, InterfacePtrType>>; |
103 friend struct ThreadSafeInterfacePtrDeleter; | 104 friend struct ThreadSafeInterfacePtrDeleter; |
104 | 105 |
105 ThreadSafeInterfacePtrBase() : proxy_(this), weak_ptr_factory_(this) {} | 106 ThreadSafeInterfacePtrBase() : proxy_(this), weak_ptr_factory_(this) {} |
106 | 107 |
107 void DeleteOnCorrectThread() const { | 108 void DeleteOnCorrectThread() const { |
108 if (interface_ptr_task_runner_ && | 109 if (interface_ptr_task_runner_ && |
109 !interface_ptr_task_runner_->BelongsToCurrentThread() && | 110 !interface_ptr_task_runner_->RunsTasksOnCurrentThread() && |
110 interface_ptr_task_runner_->DeleteSoon(FROM_HERE, this)) { | 111 interface_ptr_task_runner_->DeleteSoon(FROM_HERE, this)) { |
111 return; | 112 return; |
112 } | 113 } |
113 delete this; | 114 delete this; |
114 } | 115 } |
115 | 116 |
116 // MessageReceiverWithResponder implementation: | 117 // MessageReceiverWithResponder implementation: |
117 bool Accept(Message* message) override { | 118 bool Accept(Message* message) override { |
118 interface_ptr_task_runner_->PostTask( | 119 interface_ptr_task_runner_->PostTask( |
119 FROM_HERE, | 120 FROM_HERE, |
(...skipping 23 matching lines...) Expand all Loading... |
143 Message message, | 144 Message message, |
144 std::unique_ptr<MessageReceiver> responder) { | 145 std::unique_ptr<MessageReceiver> responder) { |
145 interface_ptr_.internal_state()->ForwardMessageWithResponder( | 146 interface_ptr_.internal_state()->ForwardMessageWithResponder( |
146 std::move(message), std::move(responder)); | 147 std::move(message), std::move(responder)); |
147 } | 148 } |
148 | 149 |
149 class ForwardToCallingThread : public MessageReceiver { | 150 class ForwardToCallingThread : public MessageReceiver { |
150 public: | 151 public: |
151 explicit ForwardToCallingThread(std::unique_ptr<MessageReceiver> responder) | 152 explicit ForwardToCallingThread(std::unique_ptr<MessageReceiver> responder) |
152 : responder_(std::move(responder)), | 153 : responder_(std::move(responder)), |
153 caller_task_runner_(base::ThreadTaskRunnerHandle::Get()) { | 154 caller_task_runner_(base::SequencedTaskRunnerHandle::Get()) {} |
154 } | |
155 | 155 |
156 private: | 156 private: |
157 bool Accept(Message* message) { | 157 bool Accept(Message* message) { |
158 // The current instance will be deleted when this method returns, so we | 158 // 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 | 159 // have to relinquish the responder's ownership so it does not get |
160 // deleted. | 160 // deleted. |
161 caller_task_runner_->PostTask(FROM_HERE, | 161 caller_task_runner_->PostTask(FROM_HERE, |
162 base::Bind(&ForwardToCallingThread::CallAcceptAndDeleteResponder, | 162 base::Bind(&ForwardToCallingThread::CallAcceptAndDeleteResponder, |
163 base::Passed(std::move(responder_)), | 163 base::Passed(std::move(responder_)), |
164 base::Passed(std::move(*message)))); | 164 base::Passed(std::move(*message)))); |
165 return true; | 165 return true; |
166 } | 166 } |
167 | 167 |
168 static void CallAcceptAndDeleteResponder( | 168 static void CallAcceptAndDeleteResponder( |
169 std::unique_ptr<MessageReceiver> responder, | 169 std::unique_ptr<MessageReceiver> responder, |
170 Message message) { | 170 Message message) { |
171 ignore_result(responder->Accept(&message)); | 171 ignore_result(responder->Accept(&message)); |
172 } | 172 } |
173 | 173 |
174 std::unique_ptr<MessageReceiver> responder_; | 174 std::unique_ptr<MessageReceiver> responder_; |
175 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_; | 175 scoped_refptr<base::SequencedTaskRunner> caller_task_runner_; |
176 }; | 176 }; |
177 | 177 |
178 scoped_refptr<base::SingleThreadTaskRunner> interface_ptr_task_runner_; | 178 scoped_refptr<base::SequencedTaskRunner> interface_ptr_task_runner_; |
179 ProxyType proxy_; | 179 ProxyType proxy_; |
180 InterfacePtrType<Interface> interface_ptr_; | 180 InterfacePtrType<Interface> interface_ptr_; |
181 base::WeakPtrFactory<ThreadSafeInterfacePtrBase> weak_ptr_factory_; | 181 base::WeakPtrFactory<ThreadSafeInterfacePtrBase> weak_ptr_factory_; |
182 }; | 182 }; |
183 | 183 |
184 struct ThreadSafeInterfacePtrDeleter { | 184 struct ThreadSafeInterfacePtrDeleter { |
185 template <typename Interface, template <typename> class InterfacePtrType> | 185 template <typename Interface, template <typename> class InterfacePtrType> |
186 static void Destruct( | 186 static void Destruct( |
187 const ThreadSafeInterfacePtrBase<Interface, InterfacePtrType>* | 187 const ThreadSafeInterfacePtrBase<Interface, InterfacePtrType>* |
188 interface_ptr) { | 188 interface_ptr) { |
189 interface_ptr->DeleteOnCorrectThread(); | 189 interface_ptr->DeleteOnCorrectThread(); |
190 } | 190 } |
191 }; | 191 }; |
192 | 192 |
193 template <typename Interface> | 193 template <typename Interface> |
194 using ThreadSafeAssociatedInterfacePtr = | 194 using ThreadSafeAssociatedInterfacePtr = |
195 ThreadSafeInterfacePtrBase<Interface, AssociatedInterfacePtr>; | 195 ThreadSafeInterfacePtrBase<Interface, AssociatedInterfacePtr>; |
196 | 196 |
197 template <typename Interface> | 197 template <typename Interface> |
198 using ThreadSafeInterfacePtr = | 198 using ThreadSafeInterfacePtr = |
199 ThreadSafeInterfacePtrBase<Interface, InterfacePtr>; | 199 ThreadSafeInterfacePtrBase<Interface, InterfacePtr>; |
200 | 200 |
201 } // namespace mojo | 201 } // namespace mojo |
202 | 202 |
203 #endif // MOJO_PUBLIC_CPP_BINDINGS_THREAD_SAFE_INTERFACE_PTR_H_ | 203 #endif // MOJO_PUBLIC_CPP_BINDINGS_THREAD_SAFE_INTERFACE_PTR_H_ |
OLD | NEW |