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

Unified Diff: mojo/public/cpp/bindings/binding_set.h

Issue 2283543002: Add support for dispatch contexts on BindingSet (Closed)
Patch Set: . Created 4 years, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « mojo/public/cpp/bindings/associated_binding_set.h ('k') | mojo/public/cpp/bindings/lib/binding_state.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mojo/public/cpp/bindings/binding_set.h
diff --git a/mojo/public/cpp/bindings/binding_set.h b/mojo/public/cpp/bindings/binding_set.h
index b1baca6a808dc3e6e637bbd408e7f424dfae828d..8b36669c799e095379e76994403d108970dc8238 100644
--- a/mojo/public/cpp/bindings/binding_set.h
+++ b/mojo/public/cpp/bindings/binding_set.h
@@ -5,107 +5,171 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_
#define MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_
-#include <algorithm>
#include <utility>
-#include <vector>
#include "base/bind.h"
#include "base/callback.h"
#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/interface_ptr.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/cpp/bindings/message.h"
namespace mojo {
+template <typename BindingType>
+struct BindingSetTraits;
+
+template <typename Interface>
+struct BindingSetTraits<Binding<Interface>> {
+ using ProxyType = InterfacePtr<Interface>;
+ using RequestType = InterfaceRequest<Interface>;
+
+ static RequestType GetProxy(ProxyType* proxy) {
+ return mojo::GetProxy(proxy);
+ }
+};
+
+enum class BindingSetDispatchMode {
+ WITHOUT_CONTEXT,
+ WITH_CONTEXT,
+};
+
// Use this class to manage a set of bindings, which are automatically destroyed
// and removed from the set when the pipe they are bound to is disconnected.
-template <typename Interface>
+template <typename Interface, typename BindingType = Binding<Interface>>
class BindingSet {
public:
- BindingSet() {}
- ~BindingSet() { CloseAllBindings(); }
+ using Traits = BindingSetTraits<BindingType>;
+ using ProxyType = typename Traits::ProxyType;
+ using RequestType = typename Traits::RequestType;
+
+ BindingSet() : BindingSet(BindingSetDispatchMode::WITHOUT_CONTEXT) {}
+
+ // Constructs a new BindingSet operating in |dispatch_mode|. If |WITH_CONTEXT|
+ // is used, AddBinding() supports a |context| argument, and dispatch_context()
+ // may be called during message or error dispatch to identify which specific
+ // binding received the message or error.
+ explicit BindingSet(BindingSetDispatchMode dispatch_mode)
+ : dispatch_mode_(dispatch_mode) {}
void set_connection_error_handler(const base::Closure& error_handler) {
error_handler_ = error_handler;
}
- void AddBinding(Interface* impl, InterfaceRequest<Interface> request) {
- auto binding = new Element(impl, std::move(request));
- binding->set_connection_error_handler(
- base::Bind(&BindingSet::OnConnectionError, base::Unretained(this)));
- bindings_.push_back(binding->GetWeakPtr());
+ // Adds a new binding to the set which binds |request| to |impl|. If |context|
+ // is non-null, dispatch_context() will reflect this value during the extent
+ // of any message or error dispatch targeting this specific binding. Note that
+ // |context| may only be non-null if the BindingSet was constructed with
+ // |BindingSetDispatchMode::WITH_CONTEXT|.
+ void AddBinding(Interface* impl,
+ RequestType request,
+ void* context = nullptr) {
+ DCHECK(!context || SupportsContext());
+ std::unique_ptr<Entry> entry =
+ base::MakeUnique<Entry>(impl, std::move(request), this, context);
+ bindings_.insert(std::make_pair(entry.get(), std::move(entry)));
}
- // Returns an InterfacePtr bound to one end of a pipe whose other end is
- // bound to |this|.
- InterfacePtr<Interface> CreateInterfacePtrAndBind(Interface* impl) {
- InterfacePtr<Interface> interface_ptr;
- AddBinding(impl, GetProxy(&interface_ptr));
- return interface_ptr;
+ // Returns a proxy bound to one end of a pipe whose other end is bound to
+ // |this|.
+ ProxyType CreateInterfacePtrAndBind(Interface* impl) {
+ ProxyType proxy;
+ AddBinding(impl, Traits::GetProxy(&proxy));
+ return proxy;
}
- void CloseAllBindings() {
- for (const auto& it : bindings_) {
- if (it) {
- it->Close();
- delete it.get();
- }
- }
- bindings_.clear();
- }
+ void CloseAllBindings() { bindings_.clear(); }
bool empty() const { return bindings_.empty(); }
+ // Implementations may call this when processing a dispatched message or
+ // error. During the extent of message or error dispatch, this will return the
+ // context associated with the specific binding which received the message or
+ // error. Use AddBinding() to associated a context with a specific binding.
+ //
+ // Note that this may ONLY be called if the BindingSet was constructed with
+ // |BindingSetDispatchMode::WITH_CONTEXT|.
+ void* dispatch_context() const {
+ DCHECK(SupportsContext());
+ return dispatch_context_;
+ }
+
private:
- class Element {
+ friend class Entry;
+
+ class Entry {
public:
- Element(Interface* impl, InterfaceRequest<Interface> request)
- : binding_(impl, std::move(request)), weak_ptr_factory_(this) {
- binding_.set_connection_error_handler(
- base::Bind(&Element::OnConnectionError, base::Unretained(this)));
+ Entry(Interface* impl,
+ RequestType request,
+ BindingSet* binding_set,
+ void* context)
+ : binding_(impl, std::move(request)),
+ binding_set_(binding_set),
+ context_(context) {
+ if (binding_set->SupportsContext())
+ binding_.AddFilter(base::MakeUnique<DispatchFilter>(this));
+ binding_.set_connection_error_handler(base::Bind(
+ &Entry::OnConnectionError, base::Unretained(this)));
}
- ~Element() {}
+ private:
+ class DispatchFilter : public MessageReceiver {
+ public:
+ explicit DispatchFilter(Entry* entry) : entry_(entry) {}
+ ~DispatchFilter() override {}
+
+ private:
+ // MessageReceiver:
+ bool Accept(Message* message) override {
+ entry_->WillDispatch();
+ return true;
+ }
- void set_connection_error_handler(const base::Closure& error_handler) {
- error_handler_ = error_handler;
- }
+ Entry* entry_;
- base::WeakPtr<Element> GetWeakPtr() {
- return weak_ptr_factory_.GetWeakPtr();
- }
+ DISALLOW_COPY_AND_ASSIGN(DispatchFilter);
+ };
- void Close() { binding_.Close(); }
+ void WillDispatch() {
+ if (binding_set_->SupportsContext())
yzshen1 2016/08/26 18:11:28 nit: we could move this check out of WillDispatch(
Ken Rockot(use gerrit already) 2016/08/26 20:15:01 Done
+ binding_set_->SetDispatchContext(context_);
+ }
void OnConnectionError() {
- base::Closure error_handler = error_handler_;
- delete this;
- if (!error_handler.is_null())
- error_handler.Run();
+ WillDispatch();
+ binding_set_->OnConnectionError(this);
}
- private:
- Binding<Interface> binding_;
- base::Closure error_handler_;
- base::WeakPtrFactory<Element> weak_ptr_factory_;
+ BindingType binding_;
+ BindingSet* const binding_set_;
+ void* const context_;
- DISALLOW_COPY_AND_ASSIGN(Element);
+ DISALLOW_COPY_AND_ASSIGN(Entry);
};
- void OnConnectionError() {
- // Clear any deleted bindings.
- bindings_.erase(std::remove_if(bindings_.begin(), bindings_.end(),
- [](const base::WeakPtr<Element>& p) {
- return p.get() == nullptr;
- }),
- bindings_.end());
+ void SetDispatchContext(void* context) {
+ DCHECK(SupportsContext());
+ dispatch_context_ = context;
+ }
+
+ bool SupportsContext() const {
+ return dispatch_mode_ == BindingSetDispatchMode::WITH_CONTEXT;
+ }
+
+ void OnConnectionError(Entry* entry) {
+ auto it = bindings_.find(entry);
+ DCHECK(it != bindings_.end());
+ bindings_.erase(it);
if (!error_handler_.is_null())
error_handler_.Run();
}
+ BindingSetDispatchMode dispatch_mode_;
base::Closure error_handler_;
- std::vector<base::WeakPtr<Element>> bindings_;
+ std::map<Entry*, std::unique_ptr<Entry>> bindings_;
+ void* dispatch_context_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(BindingSet);
};
« no previous file with comments | « mojo/public/cpp/bindings/associated_binding_set.h ('k') | mojo/public/cpp/bindings/lib/binding_state.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698