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

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

Issue 2309513002: Mojo C++ Bindings: Additional support for associated binding sets (Closed)
Patch Set: . Created 4 years, 3 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/associated_interface_ptr.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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_BINDING_SET_H_ 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_ 6 #define MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_
7 7
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 17 matching lines...) Expand all
28 static RequestType GetProxy(ProxyType* proxy) { 28 static RequestType GetProxy(ProxyType* proxy) {
29 return mojo::GetProxy(proxy); 29 return mojo::GetProxy(proxy);
30 } 30 }
31 }; 31 };
32 32
33 enum class BindingSetDispatchMode { 33 enum class BindingSetDispatchMode {
34 WITHOUT_CONTEXT, 34 WITHOUT_CONTEXT,
35 WITH_CONTEXT, 35 WITH_CONTEXT,
36 }; 36 };
37 37
38 using BindingId = size_t;
39
38 // Use this class to manage a set of bindings, which are automatically destroyed 40 // Use this class to manage a set of bindings, which are automatically destroyed
39 // and removed from the set when the pipe they are bound to is disconnected. 41 // and removed from the set when the pipe they are bound to is disconnected.
40 template <typename Interface, typename BindingType = Binding<Interface>> 42 template <typename Interface, typename BindingType = Binding<Interface>>
41 class BindingSet { 43 class BindingSet {
42 public: 44 public:
45 using PreDispatchCallback = base::Callback<void(void*)>;
43 using Traits = BindingSetTraits<BindingType>; 46 using Traits = BindingSetTraits<BindingType>;
44 using ProxyType = typename Traits::ProxyType; 47 using ProxyType = typename Traits::ProxyType;
45 using RequestType = typename Traits::RequestType; 48 using RequestType = typename Traits::RequestType;
46 49
47 BindingSet() : BindingSet(BindingSetDispatchMode::WITHOUT_CONTEXT) {} 50 BindingSet() : BindingSet(BindingSetDispatchMode::WITHOUT_CONTEXT) {}
48 51
49 // Constructs a new BindingSet operating in |dispatch_mode|. If |WITH_CONTEXT| 52 // Constructs a new BindingSet operating in |dispatch_mode|. If |WITH_CONTEXT|
50 // is used, AddBinding() supports a |context| argument, and dispatch_context() 53 // is used, AddBinding() supports a |context| argument, and dispatch_context()
51 // may be called during message or error dispatch to identify which specific 54 // may be called during message or error dispatch to identify which specific
52 // binding received the message or error. 55 // binding received the message or error.
53 explicit BindingSet(BindingSetDispatchMode dispatch_mode) 56 explicit BindingSet(BindingSetDispatchMode dispatch_mode)
54 : dispatch_mode_(dispatch_mode) {} 57 : dispatch_mode_(dispatch_mode) {}
55 58
56 void set_connection_error_handler(const base::Closure& error_handler) { 59 void set_connection_error_handler(const base::Closure& error_handler) {
57 error_handler_ = error_handler; 60 error_handler_ = error_handler;
58 } 61 }
59 62
63 // Sets a callback to be invoked immediately before dispatching any message or
64 // error received by any of the bindings in the set. This may only be used
65 // if the set was constructed with |BindingSetDispatchMode::WITH_CONTEXT|.
66 // |handler| is passed the context associated with the binding which received
67 // the message or event about to be dispatched.
68 void set_pre_dispatch_handler(const PreDispatchCallback& handler) {
69 DCHECK(SupportsContext());
70 pre_dispatch_handler_ = handler;
71 }
72
60 // Adds a new binding to the set which binds |request| to |impl|. If |context| 73 // Adds a new binding to the set which binds |request| to |impl|. If |context|
61 // is non-null, dispatch_context() will reflect this value during the extent 74 // is non-null, dispatch_context() will reflect this value during the extent
62 // of any message or error dispatch targeting this specific binding. Note that 75 // of any message or error dispatch targeting this specific binding. Note that
63 // |context| may only be non-null if the BindingSet was constructed with 76 // |context| may only be non-null if the BindingSet was constructed with
64 // |BindingSetDispatchMode::WITH_CONTEXT|. 77 // |BindingSetDispatchMode::WITH_CONTEXT|.
65 void AddBinding(Interface* impl, 78 BindingId AddBinding(Interface* impl,
66 RequestType request, 79 RequestType request,
67 void* context = nullptr) { 80 void* context = nullptr) {
68 DCHECK(!context || SupportsContext()); 81 DCHECK(!context || SupportsContext());
82 BindingId id = next_binding_id_++;
83 DCHECK_GE(next_binding_id_, 0u);
69 std::unique_ptr<Entry> entry = 84 std::unique_ptr<Entry> entry =
70 base::MakeUnique<Entry>(impl, std::move(request), this, context); 85 base::MakeUnique<Entry>(impl, std::move(request), this, id, context);
71 bindings_.insert(std::make_pair(entry.get(), std::move(entry))); 86 bindings_.insert(std::make_pair(id, std::move(entry)));
87 return id;
88 }
89
90 // Removes a binding from the set. Note that this is safe to call even if the
91 // binding corresponding to |id| has already been removed.
92 //
93 // Returns |true| if the binding was removed and |false| if it didn't exist.
94 bool RemoveBinding(BindingId id) {
95 auto it = bindings_.find(id);
96 if (it == bindings_.end())
97 return false;
98 bindings_.erase(it);
99 return true;
72 } 100 }
73 101
74 // Returns a proxy bound to one end of a pipe whose other end is bound to 102 // Returns a proxy bound to one end of a pipe whose other end is bound to
75 // |this|. 103 // |this|. If |id_storage| is not null, |*id_storage| will be set to the ID
76 ProxyType CreateInterfacePtrAndBind(Interface* impl) { 104 // of the added binding.
105 ProxyType CreateInterfacePtrAndBind(Interface* impl,
106 BindingId* id_storage = nullptr) {
77 ProxyType proxy; 107 ProxyType proxy;
78 AddBinding(impl, Traits::GetProxy(&proxy)); 108 BindingId id = AddBinding(impl, Traits::GetProxy(&proxy));
109 if (id_storage)
110 *id_storage = id;
79 return proxy; 111 return proxy;
80 } 112 }
81 113
82 void CloseAllBindings() { bindings_.clear(); } 114 void CloseAllBindings() { bindings_.clear(); }
83 115
84 bool empty() const { return bindings_.empty(); } 116 bool empty() const { return bindings_.empty(); }
85 117
86 // Implementations may call this when processing a dispatched message or 118 // Implementations may call this when processing a dispatched message or
87 // error. During the extent of message or error dispatch, this will return the 119 // error. During the extent of message or error dispatch, this will return the
88 // context associated with the specific binding which received the message or 120 // context associated with the specific binding which received the message or
(...skipping 13 matching lines...) Expand all
102 } 134 }
103 135
104 private: 136 private:
105 friend class Entry; 137 friend class Entry;
106 138
107 class Entry { 139 class Entry {
108 public: 140 public:
109 Entry(Interface* impl, 141 Entry(Interface* impl,
110 RequestType request, 142 RequestType request,
111 BindingSet* binding_set, 143 BindingSet* binding_set,
144 BindingId binding_id,
112 void* context) 145 void* context)
113 : binding_(impl, std::move(request)), 146 : binding_(impl, std::move(request)),
114 binding_set_(binding_set), 147 binding_set_(binding_set),
148 binding_id_(binding_id),
115 context_(context) { 149 context_(context) {
116 if (binding_set->SupportsContext()) 150 if (binding_set->SupportsContext())
117 binding_.AddFilter(base::MakeUnique<DispatchFilter>(this)); 151 binding_.AddFilter(base::MakeUnique<DispatchFilter>(this));
118 binding_.set_connection_error_handler(base::Bind( 152 binding_.set_connection_error_handler(base::Bind(
119 &Entry::OnConnectionError, base::Unretained(this))); 153 &Entry::OnConnectionError, base::Unretained(this)));
120 } 154 }
121 155
122 void FlushForTesting() { binding_.FlushForTesting(); } 156 void FlushForTesting() { binding_.FlushForTesting(); }
123 157
124 private: 158 private:
(...skipping 15 matching lines...) Expand all
140 }; 174 };
141 175
142 void WillDispatch() { 176 void WillDispatch() {
143 DCHECK(binding_set_->SupportsContext()); 177 DCHECK(binding_set_->SupportsContext());
144 binding_set_->SetDispatchContext(context_); 178 binding_set_->SetDispatchContext(context_);
145 } 179 }
146 180
147 void OnConnectionError() { 181 void OnConnectionError() {
148 if (binding_set_->SupportsContext()) 182 if (binding_set_->SupportsContext())
149 WillDispatch(); 183 WillDispatch();
150 binding_set_->OnConnectionError(this); 184 binding_set_->OnConnectionError(binding_id_);
151 } 185 }
152 186
153 BindingType binding_; 187 BindingType binding_;
154 BindingSet* const binding_set_; 188 BindingSet* const binding_set_;
189 const BindingId binding_id_;
155 void* const context_; 190 void* const context_;
156 191
157 DISALLOW_COPY_AND_ASSIGN(Entry); 192 DISALLOW_COPY_AND_ASSIGN(Entry);
158 }; 193 };
159 194
160 void SetDispatchContext(void* context) { 195 void SetDispatchContext(void* context) {
161 DCHECK(SupportsContext()); 196 DCHECK(SupportsContext());
162 dispatch_context_ = context; 197 dispatch_context_ = context;
198 if (!pre_dispatch_handler_.is_null())
199 pre_dispatch_handler_.Run(context);
163 } 200 }
164 201
165 bool SupportsContext() const { 202 bool SupportsContext() const {
166 return dispatch_mode_ == BindingSetDispatchMode::WITH_CONTEXT; 203 return dispatch_mode_ == BindingSetDispatchMode::WITH_CONTEXT;
167 } 204 }
168 205
169 void OnConnectionError(Entry* entry) { 206 void OnConnectionError(BindingId id) {
170 auto it = bindings_.find(entry); 207 auto it = bindings_.find(id);
171 DCHECK(it != bindings_.end()); 208 DCHECK(it != bindings_.end());
172 bindings_.erase(it); 209 bindings_.erase(it);
173 210
174 if (!error_handler_.is_null()) 211 if (!error_handler_.is_null())
175 error_handler_.Run(); 212 error_handler_.Run();
176 } 213 }
177 214
178 BindingSetDispatchMode dispatch_mode_; 215 BindingSetDispatchMode dispatch_mode_;
179 base::Closure error_handler_; 216 base::Closure error_handler_;
180 std::map<Entry*, std::unique_ptr<Entry>> bindings_; 217 PreDispatchCallback pre_dispatch_handler_;
218 BindingId next_binding_id_ = 0;
219 std::map<BindingId, std::unique_ptr<Entry>> bindings_;
181 void* dispatch_context_ = nullptr; 220 void* dispatch_context_ = nullptr;
182 221
183 DISALLOW_COPY_AND_ASSIGN(BindingSet); 222 DISALLOW_COPY_AND_ASSIGN(BindingSet);
184 }; 223 };
185 224
186 } // namespace mojo 225 } // namespace mojo
187 226
188 #endif // MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_ 227 #endif // MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_
OLDNEW
« no previous file with comments | « mojo/public/cpp/bindings/associated_interface_ptr.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698