Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2015 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_COMMON_SERVICE_SET_H_ | |
| 6 #define MOJO_COMMON_SERVICE_SET_H_ | |
| 7 | |
| 8 #include <map> | |
| 9 #include <utility> | |
| 10 | |
| 11 #include "base/bind.h" | |
| 12 #include "base/logging.h" | |
| 13 #include "base/macros.h" | |
| 14 #include "mojo/public/cpp/bindings/binding.h" | |
| 15 | |
| 16 namespace mojo { | |
| 17 | |
| 18 // A set of mojo services where each service's lifetime is bound to a message | |
| 19 // pipe to its client. The template parameters Interface and Impl should be a | |
| 20 // mojo interface and a concrete implementation of that interface, respectively. | |
| 21 // | |
| 22 // To create an instance of Impl in response to a request, call | |
| 23 // CreateService(request.Pass(), <other args to Impl's constructor>); | |
| 24 // | |
| 25 // When the client of a service closes its connection, that service is | |
| 26 // automatically destroyed. set_connection_error_handler() can be used to | |
| 27 // register an ErrorHandler to be called when this occurs. When the handler is | |
| 28 // called, the service is no longer contained in the set but is only destroyed | |
| 29 // after the callback returns. | |
| 30 // | |
| 31 // A service may be manually destroyed by calling DestroyService(). Services | |
| 32 // destroyed this way will not trigger a call to the ErrorHandler. | |
| 33 template <typename Interface, typename Impl> | |
| 34 class ServiceSet { | |
|
yzshen1
2015/11/19 17:34:24
With a quick look, this looks similar to WeakBindi
Sam McNally
2015/11/23 01:12:53
It's similar, but I think the ownership here is di
yzshen1
2015/11/23 16:12:09
What do you think about naming it StrongBindingSet
Sam McNally
2015/12/01 00:12:54
This class isn't publicly concerned with bindings.
| |
| 35 public: | |
| 36 using ErrorHandler = Callback<void(Impl*)>; | |
| 37 class Iterator; | |
| 38 | |
| 39 ServiceSet() = default; | |
| 40 | |
| 41 void set_connection_error_handler(const ErrorHandler& error_handler) { | |
| 42 error_handler_ = error_handler; | |
| 43 } | |
| 44 | |
| 45 template <typename... Args> | |
| 46 Impl* EmplaceService(InterfaceRequest<Interface> request, Args&&... args) { | |
|
danakj
2015/11/18 19:59:51
I should point out that && is not allowed to be us
| |
| 47 auto holder = make_scoped_ptr( | |
| 48 new Holder(this, request.Pass(), std::forward<Args>(args)...)); | |
| 49 Impl* impl = holder->impl(); | |
| 50 holders_.insert(std::make_pair(impl, holder.Pass())); | |
| 51 return impl; | |
| 52 } | |
| 53 | |
| 54 void DestroyService(Impl* impl) { | |
| 55 size_t num_erased = holders_.erase(impl); | |
| 56 DCHECK_EQ(1u, num_erased); | |
| 57 } | |
| 58 | |
| 59 void Clear() { holders_.clear(); } | |
| 60 | |
| 61 bool empty() const { return holders_.empty(); } | |
| 62 size_t size() const { return holders_.size(); } | |
| 63 Iterator begin() const { return Iterator(holders_.begin()); } | |
| 64 Iterator end() const { return Iterator(holders_.end()); } | |
| 65 | |
| 66 private: | |
| 67 class Holder; | |
| 68 using Container = std::map<Impl*, scoped_ptr<Holder>>; | |
| 69 | |
| 70 void OnConnectionError(Holder* holder) { | |
| 71 Impl* impl = holder->impl(); | |
| 72 auto it = holders_.find(holder->impl()); | |
| 73 DCHECK(it != holders_.end()); | |
| 74 scoped_ptr<Holder> holder_owner = it->second.Pass(); | |
| 75 holders_.erase(it); | |
| 76 if (!error_handler_.is_null()) | |
| 77 error_handler_.Run(impl); | |
| 78 } | |
| 79 | |
| 80 ErrorHandler error_handler_; | |
| 81 Container holders_; | |
| 82 | |
| 83 DISALLOW_COPY_AND_ASSIGN(ServiceSet); | |
| 84 }; | |
| 85 | |
| 86 template <typename Interface, typename Impl> | |
| 87 class ServiceSet<Interface, Impl>::Holder { | |
| 88 public: | |
| 89 template <typename... Args> | |
| 90 Holder(ServiceSet* service_set, | |
| 91 InterfaceRequest<Interface> request, | |
| 92 Args&&... args) | |
| 93 : impl_(std::forward<Args>(args)...), | |
| 94 binding_(&impl_, request.Pass()), | |
| 95 service_set_(service_set) { | |
| 96 binding_.set_connection_error_handler( | |
| 97 base::Bind(&Holder::OnConnectionError, base::Unretained(this))); | |
| 98 } | |
| 99 | |
| 100 void OnConnectionError() { service_set_->OnConnectionError(this); } | |
| 101 | |
| 102 Impl* impl() { return &impl_; } | |
| 103 | |
| 104 private: | |
| 105 Impl impl_; | |
| 106 Binding<Interface> binding_; | |
| 107 | |
| 108 // Owns this. | |
| 109 ServiceSet* const service_set_; | |
| 110 | |
| 111 DISALLOW_COPY_AND_ASSIGN(Holder); | |
| 112 }; | |
| 113 | |
| 114 template <typename Interface, typename Impl> | |
| 115 class ServiceSet<Interface, Impl>::Iterator { | |
| 116 public: | |
| 117 using iterator_category = std::input_iterator_tag; | |
| 118 using difference_type = std::ptrdiff_t; | |
| 119 using value_type = Impl*; | |
| 120 using pointer = value_type*; | |
| 121 using reference = value_type&; | |
| 122 | |
| 123 Iterator() = default; | |
| 124 | |
| 125 Iterator& operator++() { | |
| 126 ++it_; | |
| 127 return *this; | |
| 128 } | |
| 129 | |
| 130 Impl* operator*() const { return it_->first; } | |
| 131 Impl* operator->() const { return it_->first; } | |
| 132 bool operator==(const Iterator& other) const { return it_ == other.it_; } | |
| 133 bool operator!=(const Iterator& other) const { return it_ != other.it_; } | |
| 134 | |
| 135 private: | |
| 136 using IteratorImpl = typename Container::const_iterator; | |
| 137 friend class ServiceSet; | |
| 138 | |
| 139 explicit Iterator(IteratorImpl it) : it_(it) {} | |
| 140 | |
| 141 IteratorImpl it_; | |
| 142 }; | |
| 143 | |
| 144 } // namespace mojo | |
| 145 | |
| 146 #endif // MOJO_COMMON_SERVICE_SET_H_ | |
| OLD | NEW |