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

Side by Side Diff: mojo/common/strong_binding_set.h

Issue 1411063007: Add mojo::StrongBindingSet and use it in GeolocationServiceContext. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years 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/common/BUILD.gn ('k') | mojo/common/strong_binding_set_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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_STRONG_BINDING_SET_H_
6 #define MOJO_COMMON_STRONG_BINDING_SET_H_
7
8 #include <iterator>
9 #include <map>
10 #include <type_traits>
11 #include <utility>
12
13 #include "base/bind.h"
14 #include "base/logging.h"
15 #include "base/macros.h"
16 #include "mojo/public/cpp/bindings/binding.h"
17
18 namespace mojo {
19
20 // A set of mojo services where each service's lifetime is bound to a message
21 // pipe to its client. The template parameter Impl should be a
22 // a concrete implementation of a mojo interface. The InterfaceOverride template
23 // parameter is only required if Impl implements more than one mojo interface.
24 //
25 // To create an instance of Impl in response to a request, call
26 // EmplaceService(std::move(request), <other args to Impl's constructor>);
27 //
28 // When the client of a service closes its connection, that service is
29 // automatically destroyed. set_connection_error_handler() can be used to
30 // register an ErrorHandler to be called when this occurs. When the handler is
31 // called, the service is no longer contained in the set but is only destroyed
32 // after the callback returns.
33 //
34 // A service may be manually destroyed by calling DestroyService(). Services
35 // destroyed this way will not trigger a call to the ErrorHandler.
36 template <typename Impl, typename InterfaceOverride = Impl>
37 class StrongBindingSet {
38 public:
39 using ErrorHandler = Callback<void(Impl*)>;
40 class Iterator;
41 using Interface = typename std::decay<decltype(
42 *std::declval<typename InterfaceOverride::Stub_>().sink())>::type;
43
44 StrongBindingSet() = default;
45
46 void set_connection_error_handler(const ErrorHandler& error_handler) {
47 error_handler_ = error_handler;
48 }
49
50 template <typename... Args>
51 Impl* EmplaceService(InterfaceRequest<Interface> request,
52 Args&&... args) {
53 auto holder = make_scoped_ptr(
54 new Holder(this, std::move(request), std::forward<Args>(args)...));
55 Impl* impl = holder->impl();
56 holders_.insert(std::make_pair(impl, std::move(holder)));
57 return impl;
58 }
59
60 void DestroyService(Impl* impl) {
61 size_t num_erased = holders_.erase(impl);
62 DCHECK_EQ(1u, num_erased);
63 }
64
65 void Clear() { holders_.clear(); }
66
67 bool empty() const { return holders_.empty(); }
68 size_t size() const { return holders_.size(); }
69 Iterator begin() const { return Iterator(holders_.begin()); }
70 Iterator end() const { return Iterator(holders_.end()); }
71
72 private:
73 class Holder;
74 using Container = std::map<Impl*, scoped_ptr<Holder>>;
75
76 void OnConnectionError(Holder* holder) {
77 Impl* impl = holder->impl();
78 auto it = holders_.find(holder->impl());
79 DCHECK(it != holders_.end());
80 scoped_ptr<Holder> holder_owner = std::move(it->second);
81 holders_.erase(it);
82 if (!error_handler_.is_null())
83 error_handler_.Run(impl);
84 }
85
86 ErrorHandler error_handler_;
87 Container holders_;
88
89 DISALLOW_COPY_AND_ASSIGN(StrongBindingSet);
90 };
91
92 template <typename Impl, typename Interface>
93 class StrongBindingSet<Impl, Interface>::Holder {
94 public:
95 template <typename... Args>
96 Holder(StrongBindingSet* service_set,
97 InterfaceRequest<Interface> request,
98 Args&&... args)
99 : impl_(std::forward<Args>(args)...),
100 binding_(&impl_, std::move(request)),
101 service_set_(service_set) {
102 binding_.set_connection_error_handler(
103 base::Bind(&Holder::OnConnectionError, base::Unretained(this)));
104 }
105
106 void OnConnectionError() { service_set_->OnConnectionError(this); }
107
108 Impl* impl() { return &impl_; }
109
110 private:
111 Impl impl_;
112 Binding<Interface> binding_;
113
114 // Owns this.
115 StrongBindingSet* const service_set_;
116
117 DISALLOW_COPY_AND_ASSIGN(Holder);
118 };
119
120 template <typename Impl, typename Interface>
121 class StrongBindingSet<Impl, Interface>::Iterator
122 : public std::iterator<std::bidirectional_iterator_tag, Impl*> {
123 public:
124 Iterator() = default;
125
126 Iterator& operator++() {
127 ++it_;
128 return *this;
129 }
130
131 Iterator operator++(int) { return Iterator(it_++); }
132
133 Iterator& operator--() {
134 --it_;
135 return *this;
136 }
137
138 Iterator operator--(int) { return Iterator(it_--); }
139
140 Impl* operator*() const { return it_->first; }
141 Impl* operator->() const { return it_->first; }
142 bool operator==(const Iterator& other) const { return it_ == other.it_; }
143 bool operator!=(const Iterator& other) const { return it_ != other.it_; }
144
145 private:
146 using IteratorImpl = typename Container::const_iterator;
147 friend class StrongBindingSet;
148
149 explicit Iterator(IteratorImpl it) : it_(it) {}
150
151 IteratorImpl it_;
152 };
153
154 } // namespace mojo
155
156 #endif // MOJO_COMMON_STRONG_BINDING_SET_H_
OLDNEW
« no previous file with comments | « mojo/common/BUILD.gn ('k') | mojo/common/strong_binding_set_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698