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

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

Issue 2498743002: Mojo: introducing a thread safe interface pointer. (Closed)
Patch Set: Fix Android compile 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_THREAD_SAFE_INTERFACE_PTR_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_THREAD_SAFE_INTERFACE_PTR_H_
7
8 namespace mojo {
9
10 #include <memory>
11
12 #include "base/callback.h"
13 #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"
17 #include "mojo/public/cpp/bindings/interface_ptr.h"
18 #include "mojo/public/cpp/bindings/lib/interface_ptr_state.h"
19 #include "mojo/public/cpp/bindings/message.h"
20
21 struct ThreadSafeInterfacePtrDeleter;
22
23 // ThreadSafeInterfacePtr is a version of InterfacePtr that lets caller invoke
24 // interface methods from any threads. Callbacks are called on the thread that
25 // performed the interface call.
26 // To create a ThreadSafeInterfacePtr, create first a regular InterfacePtr that
27 // you then provide to ThreadSafeInterfacePtr::Create.
28 // You can then call methods on the ThreadSafeInterfacePtr from any thread.
29 //
30 // Ex:
31 // frob::FrobinatorPtr frobinator;
32 // frob::FrobinatorImpl impl(GetProxy(&frobinator));
33 // scoped_refptr<frob::ThreadSafeFrobinatorPtr> thread_safe_frobinator =
34 // frob::ThreadSafeFrobinatorPtr::Create(std::move(frobinator));
35 // (*thread_safe_frobinator)->FrobinateToTheMax();
36
37 template <typename Interface>
38 class ThreadSafeInterfacePtr : public MessageReceiverWithResponder,
39 public base::RefCountedThreadSafe<ThreadSafeInterfacePtr<Interface>,
40 ThreadSafeInterfacePtrDeleter> {
41 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 ThreadSafeInterfacePtr<Interface>* Create(
yzshen1 2016/11/15 18:53:46 It seems better to return a scoped_refptr.
Jay Civelli 2016/11/15 19:36:38 Good idea, done.
53 InterfacePtr<Interface> interface_ptr) {
54 return new ThreadSafeInterfacePtr(std::move(interface_ptr),
yzshen1 2016/11/15 18:53:46 Please also deal with the case where interface_ptr
Jay Civelli 2016/11/15 19:36:38 Done.
55 base::ThreadTaskRunnerHandle::Get());
56 }
57
yzshen1 2016/11/15 18:53:46 Do we need to also expose connection error handler
Jay Civelli 2016/11/15 19:36:38 That's a good question. Happy to add them to Threa
yzshen1 2016/11/15 20:26:15 Yeah. I think that makes sense.
58 private:
59 friend class base::RefCountedThreadSafe<ThreadSafeInterfacePtr<Interface>>;
60 friend struct ThreadSafeInterfacePtrDeleter;
61
62 ThreadSafeInterfacePtr(
63 InterfacePtr<Interface> interface_ptr,
64 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
65 : interface_ptr_task_runner_(task_runner),
66 proxy_(this),
67 interface_ptr_(std::move(interface_ptr)) {
68 // Note that it's important we do get the callback after interface_ptr_ has
69 // been set, as they would become invalid if interface_ptr_ is copied.
70 accept_callback_ = interface_ptr_.internal_state()->
71 GetThreadSafePtrAcceptCallback();
72 accept_with_responder_callback_ = interface_ptr_.internal_state()->
73 GetThreadSafePtrAcceptWithResponderCallback();
74 }
75
76 void DeleteOnCorrectThread() const {
77 if (!interface_ptr_task_runner_->BelongsToCurrentThread() &&
78 interface_ptr_task_runner_->DeleteSoon(FROM_HERE, this)) {
79 return;
80 }
81 delete this;
82 }
83
84 // MessageReceiverWithResponder implementation:
85 bool Accept(Message* message) override {
86 interface_ptr_task_runner_->PostTask(
87 FROM_HERE,
88 base::Bind(accept_callback_, base::Passed(std::move(*message))));
89 return true;
90 }
91
92 bool AcceptWithResponder(Message* message,
93 MessageReceiver* responder) override {
94 auto forward_responder = base::MakeUnique<ForwardToCallingThread>(
95 base::WrapUnique(responder));
96 interface_ptr_task_runner_->PostTask(
97 FROM_HERE,
98 base::Bind(accept_with_responder_callback_,
99 base::Passed(std::move(*message)),
100 base::Passed(std::move(forward_responder))));
101 return true;
102 }
103
104 class ForwardToCallingThread : public MessageReceiver {
105 public:
106 explicit ForwardToCallingThread(std::unique_ptr<MessageReceiver> responder)
107 : responder_(std::move(responder)),
108 caller_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
109 }
110
111 private:
112 bool Accept(Message* message) {
113 // The current instance will be deleted when this method returns, so we
114 // have to relinquish the responder's ownership so it does not get
115 // deleted.
116 caller_task_runner_->PostTask(FROM_HERE,
117 base::Bind(&ForwardToCallingThread::CallAcceptAndDeleteResponder,
118 base::Passed(std::move(responder_)),
119 base::Passed(std::move(*message))));
120 return true;
121 }
122
123 static void CallAcceptAndDeleteResponder(
124 std::unique_ptr<MessageReceiver> responder,
125 Message message) {
126 ignore_result(responder->Accept(&message));
127 }
128
129 std::unique_ptr<MessageReceiver> responder_;
130 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
131 };
132
133 scoped_refptr<base::SingleThreadTaskRunner> interface_ptr_task_runner_;
134 ProxyType proxy_;
135 AcceptCallback accept_callback_;
136 AcceptWithResponderCallback accept_with_responder_callback_;
137 InterfacePtr<Interface> interface_ptr_;
138 };
139
140 struct ThreadSafeInterfacePtrDeleter {
141 template <typename Interface>
142 static void Destruct(const ThreadSafeInterfacePtr<Interface>* interface_ptr) {
143 interface_ptr->DeleteOnCorrectThread();
144 }
145 };
146
147 } // namespace mojo
148
149 #endif // MOJO_PUBLIC_CPP_BINDINGS_THREAD_SAFE_INTERFACE_PTR_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698