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