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 "third_party/mojo/src/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 { | |
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* CreateService(InterfaceRequest<Interface> request, Args&&... args) { | |
danakj
2015/11/17 21:42:17
Consider putting Emplace in the name so people rea
Sam McNally
2015/11/18 03:17:18
Done.
| |
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(); } | |
danakj
2015/11/17 21:42:17
These aren't member var accessors, they should be
Sam McNally
2015/11/18 03:17:18
empty() and size() are both cheap; begin() and end
danakj
2015/11/18 19:59:11
Oh, I re-read the style guide, as I've been readin
| |
60 bool empty() const { return holders_.empty(); } | |
61 size_t size() const { return holders_.size(); } | |
62 Iterator begin() const { return Iterator(holders_.begin()); } | |
63 Iterator end() const { return Iterator(holders_.end()); } | |
64 | |
65 private: | |
66 class Holder; | |
67 using Container = std::map<Impl*, scoped_ptr<Holder>>; | |
danakj
2015/11/17 21:42:17
Consider not using a typedef that is only referred
Sam McNally
2015/11/18 03:17:18
It's also used by ServiceSet::Iterator.
| |
68 | |
69 void OnConnectionError(Holder* holder) { | |
70 Impl* impl = holder->impl(); | |
71 auto it = holders_.find(holder->impl()); | |
72 DCHECK(it != holders_.end()); | |
73 scoped_ptr<Holder> holder_owner = it->second.Pass(); | |
74 holders_.erase(it); | |
75 if (!error_handler_.is_null()) | |
76 error_handler_.Run(impl); | |
77 } | |
78 | |
79 ErrorHandler error_handler_; | |
80 Container holders_; | |
81 | |
82 DISALLOW_COPY_AND_ASSIGN(ServiceSet); | |
83 }; | |
84 | |
85 template <typename Interface, typename Impl> | |
86 class ServiceSet<Interface, Impl>::Holder { | |
87 public: | |
88 template <typename... Args> | |
89 Holder(ServiceSet* service_set, | |
90 InterfaceRequest<Interface> request, | |
91 Args&&... args) | |
92 : impl_(std::forward<Args>(args)...), | |
93 binding_(&impl_, request.Pass()), | |
94 service_set_(service_set) { | |
95 binding_.set_connection_error_handler( | |
96 base::Bind(&Holder::OnConnectionError, base::Unretained(this))); | |
97 } | |
98 | |
99 void OnConnectionError() { service_set_->OnConnectionError(this); } | |
100 | |
101 Impl* impl() { return &impl_; } | |
102 | |
103 private: | |
104 Impl impl_; | |
105 Binding<Interface> binding_; | |
106 | |
107 // Owns this. | |
108 ServiceSet* const service_set_; | |
109 | |
110 DISALLOW_COPY_AND_ASSIGN(Holder); | |
111 }; | |
112 | |
113 template <typename Interface, typename Impl> | |
114 class ServiceSet<Interface, Impl>::Iterator { | |
115 public: | |
116 using iterator_category = std::input_iterator_tag; | |
117 using difference_type = std::ptrdiff_t; | |
118 using value_type = Impl*; | |
119 using pointer = value_type*; | |
120 using reference = value_type&; | |
121 | |
122 Iterator() = default; | |
123 | |
124 Iterator& operator++() { | |
125 ++it_; | |
126 return *this; | |
127 } | |
128 | |
129 Impl* operator*() const { return it_->first; } | |
130 Impl* operator->() const { return it_->first; } | |
131 bool operator==(const Iterator& other) const { return it_ == other.it_; } | |
132 bool operator!=(const Iterator& other) const { return it_ != other.it_; } | |
133 | |
134 private: | |
135 using IteratorImpl = typename Container::const_iterator; | |
136 friend class ServiceSet; | |
137 | |
138 explicit Iterator(IteratorImpl it) : it_(it) {} | |
139 | |
140 IteratorImpl it_; | |
141 }; | |
142 | |
143 } // namespace mojo | |
144 | |
145 #endif // MOJO_COMMON_SERVICE_SET_H_ | |
OLD | NEW |