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

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

Issue 2506383002: Mojo: adding a thread safe associated interface ptr. (Closed)
Patch Set: Fixed BUILD.gn Created 4 years, 1 month 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
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 namespace mojo {
9
10 #include <memory> 8 #include <memory>
11 9
12 #include "base/callback.h"
13 #include "base/macros.h" 10 #include "base/macros.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/task_runner.h"
16 #include "base/threading/thread_task_runner_handle.h" 11 #include "base/threading/thread_task_runner_handle.h"
17 #include "mojo/public/cpp/bindings/interface_ptr.h" 12 #include "mojo/public/cpp/bindings/interface_ptr.h"
18 #include "mojo/public/cpp/bindings/lib/interface_ptr_state.h" 13 #include "mojo/public/cpp/bindings/lib/interface_ptr_state.h"
14 #include "mojo/public/cpp/bindings/lib/thread_safe_interface_ptr_base.h"
19 #include "mojo/public/cpp/bindings/message.h" 15 #include "mojo/public/cpp/bindings/message.h"
20 16
21 struct ThreadSafeInterfacePtrDeleter; 17 namespace mojo {
22 18
23 // ThreadSafeInterfacePtr is a version of InterfacePtr that lets caller invoke 19 // ThreadSafeInterfacePtr is a version of InterfacePtr that lets caller invoke
24 // interface methods from any threads. Callbacks are called on the thread that 20 // interface methods from any threads. Callbacks are called on the thread that
25 // performed the interface call. 21 // performed the interface call.
26 // To create a ThreadSafeInterfacePtr, create first a regular InterfacePtr that 22 // To create a ThreadSafeInterfacePtr, create first a regular InterfacePtr that
27 // you then provide to ThreadSafeInterfacePtr::Create. 23 // you then provide to ThreadSafeInterfacePtr::Create.
28 // You can then call methods on the ThreadSafeInterfacePtr from any thread. 24 // You can then call methods on the ThreadSafeInterfacePtr from any thread.
29 // 25 //
30 // Ex: 26 // Ex:
31 // frob::FrobinatorPtr frobinator; 27 // frob::FrobinatorPtr frobinator;
32 // frob::FrobinatorImpl impl(GetProxy(&frobinator)); 28 // frob::FrobinatorImpl impl(GetProxy(&frobinator));
33 // scoped_refptr<frob::ThreadSafeFrobinatorPtr> thread_safe_frobinator = 29 // scoped_refptr<frob::ThreadSafeFrobinatorPtr> thread_safe_frobinator =
34 // frob::ThreadSafeFrobinatorPtr::Create(std::move(frobinator)); 30 // frob::ThreadSafeFrobinatorPtr::Create(std::move(frobinator));
35 // (*thread_safe_frobinator)->FrobinateToTheMax(); 31 // (*thread_safe_frobinator)->FrobinateToTheMax();
36 32
37 template <typename Interface> 33 template <typename Interface>
38 class ThreadSafeInterfacePtr : public MessageReceiverWithResponder, 34 class ThreadSafeInterfacePtr : public ThreadSafeInterfacePtrBase<Interface> {
39 public base::RefCountedThreadSafe<ThreadSafeInterfacePtr<Interface>,
40 ThreadSafeInterfacePtrDeleter> {
41 public: 35 public:
42 using ProxyType = typename Interface::Proxy_;
43
44 using AcceptCallback = base::Callback<void(Message)>;
45 using AcceptWithResponderCallback =
46 base::Callback<void(Message, std::unique_ptr<MessageReceiver>)>;
47
48 Interface* get() { return &proxy_; }
49 Interface* operator->() { return get(); }
50 Interface& operator*() { return *get(); }
51
52 static scoped_refptr<ThreadSafeInterfacePtr<Interface>> Create( 36 static scoped_refptr<ThreadSafeInterfacePtr<Interface>> Create(
53 InterfacePtr<Interface> interface_ptr) { 37 InterfacePtr<Interface> interface_ptr) {
54 if (!interface_ptr.is_bound()) { 38 if (!interface_ptr.is_bound()) {
55 LOG(ERROR) << "Attempting to create a ThreadSafeInterfacePtr from an " 39 LOG(ERROR) << "Attempting to create a ThreadSafeInterfacePtr from an "
56 "unbound InterfacePtr."; 40 "unbound InterfacePtr.";
57 return nullptr; 41 return nullptr;
58 } 42 }
59 return new ThreadSafeInterfacePtr(std::move(interface_ptr), 43 return new ThreadSafeInterfacePtr(std::move(interface_ptr),
60 base::ThreadTaskRunnerHandle::Get()); 44 base::ThreadTaskRunnerHandle::Get());
61 } 45 }
62 46
47 protected:
48 // ThreadSafeInterfacePtrBase implementation:
49 void AcceptOnInterfacePtrThread(Message message) override {
50 interface_ptr_.internal_state()->ForwardMessage(std::move(message));
51 }
52 void AcceptWithResponderOnInterfacePtrThread(
53 Message message, std::unique_ptr<MessageReceiver> responder) override {
54 interface_ptr_.internal_state()->ForwardMessageWithResponder(
55 std::move(message), std::move(responder));
56 }
57
63 private: 58 private:
64 friend class base::RefCountedThreadSafe<ThreadSafeInterfacePtr<Interface>>;
65 friend struct ThreadSafeInterfacePtrDeleter;
66
67 ThreadSafeInterfacePtr( 59 ThreadSafeInterfacePtr(
68 InterfacePtr<Interface> interface_ptr, 60 InterfacePtr<Interface> interface_ptr,
69 scoped_refptr<base::SingleThreadTaskRunner> task_runner) 61 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
70 : interface_ptr_task_runner_(task_runner), 62 : ThreadSafeInterfacePtrBase<Interface>(task_runner),
71 proxy_(this),
72 interface_ptr_(std::move(interface_ptr)) { 63 interface_ptr_(std::move(interface_ptr)) {
73 // Note that it's important we do get the callback after interface_ptr_ has
74 // been set, as they would become invalid if interface_ptr_ is copied.
75 accept_callback_ = interface_ptr_.internal_state()->
76 GetThreadSafePtrAcceptCallback();
77 accept_with_responder_callback_ = interface_ptr_.internal_state()->
78 GetThreadSafePtrAcceptWithResponderCallback();
79 } 64 }
80 65
81 void DeleteOnCorrectThread() const {
82 if (!interface_ptr_task_runner_->BelongsToCurrentThread() &&
83 interface_ptr_task_runner_->DeleteSoon(FROM_HERE, this)) {
84 return;
85 }
86 delete this;
87 }
88
89 // MessageReceiverWithResponder implementation:
90 bool Accept(Message* message) override {
91 interface_ptr_task_runner_->PostTask(
92 FROM_HERE,
93 base::Bind(accept_callback_, base::Passed(std::move(*message))));
94 return true;
95 }
96
97 bool AcceptWithResponder(Message* message,
98 MessageReceiver* responder) override {
99 auto forward_responder = base::MakeUnique<ForwardToCallingThread>(
100 base::WrapUnique(responder));
101 interface_ptr_task_runner_->PostTask(
102 FROM_HERE,
103 base::Bind(accept_with_responder_callback_,
104 base::Passed(std::move(*message)),
105 base::Passed(std::move(forward_responder))));
106 return true;
107 }
108
109 class ForwardToCallingThread : public MessageReceiver {
110 public:
111 explicit ForwardToCallingThread(std::unique_ptr<MessageReceiver> responder)
112 : responder_(std::move(responder)),
113 caller_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
114 }
115
116 private:
117 bool Accept(Message* message) {
118 // The current instance will be deleted when this method returns, so we
119 // have to relinquish the responder's ownership so it does not get
120 // deleted.
121 caller_task_runner_->PostTask(FROM_HERE,
122 base::Bind(&ForwardToCallingThread::CallAcceptAndDeleteResponder,
123 base::Passed(std::move(responder_)),
124 base::Passed(std::move(*message))));
125 return true;
126 }
127
128 static void CallAcceptAndDeleteResponder(
129 std::unique_ptr<MessageReceiver> responder,
130 Message message) {
131 ignore_result(responder->Accept(&message));
132 }
133
134 std::unique_ptr<MessageReceiver> responder_;
135 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
136 };
137
138 scoped_refptr<base::SingleThreadTaskRunner> interface_ptr_task_runner_;
139 ProxyType proxy_;
140 AcceptCallback accept_callback_;
141 AcceptWithResponderCallback accept_with_responder_callback_;
142 InterfacePtr<Interface> interface_ptr_; 66 InterfacePtr<Interface> interface_ptr_;
143 }; 67 };
144 68
145 struct ThreadSafeInterfacePtrDeleter {
146 template <typename Interface>
147 static void Destruct(const ThreadSafeInterfacePtr<Interface>* interface_ptr) {
148 interface_ptr->DeleteOnCorrectThread();
149 }
150 };
151
152 } // namespace mojo 69 } // namespace mojo
153 70
154 #endif // MOJO_PUBLIC_CPP_BINDINGS_THREAD_SAFE_INTERFACE_PTR_H_ 71 #endif // MOJO_PUBLIC_CPP_BINDINGS_THREAD_SAFE_INTERFACE_PTR_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698