rippled
Loading...
Searching...
No Matches
io_list.h
1#ifndef XRPL_SERVER_IO_LIST_H_INCLUDED
2#define XRPL_SERVER_IO_LIST_H_INCLUDED
3
4#include <boost/container/flat_map.hpp>
5
6#include <condition_variable>
7#include <functional>
8#include <memory>
9#include <mutex>
10#include <type_traits>
11#include <utility>
12
13namespace ripple {
14
16class io_list final
17{
18public:
19 class work
20 {
21 template <class = void>
22 void
23 destroy();
24
25 friend class io_list;
26 io_list* ios_ = nullptr;
27
28 public:
29 virtual ~work()
30 {
31 destroy();
32 }
33
40 io_list&
42 {
43 return *ios_;
44 }
45
46 virtual void
47 close() = 0;
48 };
49
50private:
51 template <class = void>
52 void
53 destroy();
54
57 bool closed_ = false;
59 boost::container::flat_map<work*, std::weak_ptr<work>> map_;
60 std::function<void(void)> f_;
61
62public:
63 io_list() = default;
64
74 {
75 destroy();
76 }
77
84 bool
85 closed() const
86 {
87 return closed_;
88 }
89
108 template <class T, class... Args>
110 emplace(Args&&... args);
111
130 template <class Finisher>
131 void
132 close(Finisher&& f);
133
134 void
136 {
137 close([] {});
138 }
139
154 template <class = void>
155 void
156 join();
157};
158
159//------------------------------------------------------------------------------
160
161template <class>
162void
164{
165 if (!ios_)
166 return;
167 std::function<void(void)> f;
168 {
169 std::lock_guard lock(ios_->m_);
170 ios_->map_.erase(this);
171 if (--ios_->n_ == 0 && ios_->closed_)
172 {
173 std::swap(f, ios_->f_);
175 }
176 }
177 if (f)
178 f();
179}
180
181template <class>
182void
184{
185 close();
186 join();
187}
188
189template <class T, class... Args>
191io_list::emplace(Args&&... args)
192{
193 static_assert(
194 std::is_base_of<work, T>::value, "T must derive from io_list::work");
195 if (closed_)
196 return nullptr;
197 auto sp = std::make_shared<T>(std::forward<Args>(args)...);
198 decltype(sp) dead;
199
200 std::lock_guard lock(m_);
201 if (!closed_)
202 {
203 ++n_;
204 sp->work::ios_ = this;
205 map_.emplace(sp.get(), sp);
206 }
207 else
208 {
209 std::swap(sp, dead);
210 }
211 return sp;
212}
213
214template <class Finisher>
215void
216io_list::close(Finisher&& f)
217{
219 if (closed_)
220 return;
221 closed_ = true;
222 auto map = std::move(map_);
223 if (!map.empty())
224 {
226 lock.unlock();
227 for (auto const& p : map)
228 if (auto sp = p.second.lock())
229 sp->close();
230 }
231 else
232 {
233 lock.unlock();
234 f();
235 }
236}
237
238template <class>
239void
241{
243 cv_.wait(lock, [&] { return closed_ && n_ == 0; });
244}
245
246} // namespace ripple
247
248#endif
virtual void close()=0
io_list & ios()
Return the io_list associated with the work.
Definition io_list.h:41
Manages a set of objects performing asynchronous I/O.
Definition io_list.h:17
void destroy()
Definition io_list.h:183
std::size_t n_
Definition io_list.h:56
std::mutex m_
Definition io_list.h:55
~io_list()
Destroy the list.
Definition io_list.h:73
bool closed() const
Return true if the list is closed.
Definition io_list.h:85
void join()
Block until the io_list stops.
Definition io_list.h:240
boost::container::flat_map< work *, std::weak_ptr< work > > map_
Definition io_list.h:59
std::shared_ptr< T > emplace(Args &&... args)
Create associated work if not closed.
Definition io_list.h:191
std::function< void(void)> f_
Definition io_list.h:60
std::condition_variable cv_
Definition io_list.h:58
io_list()=default
T is_same_v
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
T swap(T... args)