Index: media/mojo/services/strong_binding_set.h |
diff --git a/media/mojo/services/strong_binding_set.h b/media/mojo/services/strong_binding_set.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..fb1142de96abdeab1773d986539cc74872628342 |
--- /dev/null |
+++ b/media/mojo/services/strong_binding_set.h |
@@ -0,0 +1,97 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef MEDIA_MOJO_SERVICES_STRONG_BINDING_SET_H_ |
+#define MEDIA_MOJO_SERVICES_STRONG_BINDING_SET_H_ |
+ |
+#include <map> |
+#include <memory> |
+#include <utility> |
+ |
+#include "base/bind.h" |
+#include "base/macros.h" |
+#include "base/memory/ptr_util.h" |
+#include "mojo/public/cpp/bindings/binding.h" |
+#include "mojo/public/cpp/bindings/interface_request.h" |
+ |
+namespace media { |
+ |
+// This class manages a set of bindings. When the pipe a binding is bound to is |
+// disconnected, the binding is automatically destroyed and removed from the |
+// set, and the interface implementation is deleted. When the StrongBindingSet |
+// is destructed, all outstanding bindings in the set are destroyed and all the |
+// bound interface implementations are automatically deleted. |
+template <typename Interface> |
+class StrongBindingSet { |
+ public: |
+ using BindingId = size_t; |
+ using RequestType = mojo::InterfaceRequest<Interface>; |
+ |
+ StrongBindingSet() {} |
+ ~StrongBindingSet() {} |
+ |
+ // Adds a new binding to the set which binds |request| to |impl|. |
+ BindingId AddBinding(std::unique_ptr<Interface> impl, RequestType request) { |
+ BindingId binding_id = next_binding_id_++; |
+ std::unique_ptr<Entry> entry = base::MakeUnique<Entry>( |
+ std::move(impl), std::move(request), this, binding_id); |
+ bindings_.insert(std::make_pair(binding_id, std::move(entry))); |
+ return binding_id; |
+ } |
+ |
+ // Removes a binding from the set. Note that this is safe to call even if the |
+ // binding corresponding to |binding_id| has already been removed. |
+ // Returns |true| if the binding was removed and |false| if it didn't exist. |
+ bool RemoveBinding(BindingId binding_id) { |
+ auto it = bindings_.find(binding_id); |
+ if (it == bindings_.end()) |
+ return false; |
+ bindings_.erase(it); |
+ return true; |
+ } |
+ |
+ private: |
+ class Entry { |
+ public: |
+ Entry(std::unique_ptr<Interface> impl, |
+ RequestType request, |
+ StrongBindingSet* binding_set, |
+ BindingId binding_id) |
+ : impl_(std::move(impl)), |
+ binding_(impl_.get(), std::move(request)), |
+ binding_set_(binding_set), |
+ binding_id_(binding_id) { |
+ // base::Unretained() is safe because |this| is owned by the |
+ // |binding_set|. |
+ binding_.set_connection_error_with_reason_handler( |
+ base::Bind(&StrongBindingSet::OnConnectionError, |
+ base::Unretained(binding_set), binding_id)); |
+ } |
+ |
+ // Holds ownership of the interface implementation. |
+ std::unique_ptr<Interface> impl_; |
+ |
+ mojo::Binding<Interface> binding_; |
+ StrongBindingSet* const binding_set_; |
+ const BindingId binding_id_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(Entry); |
+ }; |
+ |
+ void OnConnectionError(BindingId binding_id, |
+ uint32_t custom_reason, |
+ const std::string& description) { |
+ bool success = RemoveBinding(binding_id); |
+ DCHECK(success) << "Binding for ID " << binding_id << " does not exist."; |
+ } |
+ |
+ std::map<BindingId, std::unique_ptr<Entry>> bindings_; |
+ BindingId next_binding_id_ = 0; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(StrongBindingSet); |
+}; |
+ |
+} // namespace media |
+ |
+#endif // MEDIA_MOJO_SERVICES_STRONG_BINDING_SET_H_ |