rippled
io_list.h
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #ifndef RIPPLE_SERVER_IO_LIST_H_INCLUDED
21 #define RIPPLE_SERVER_IO_LIST_H_INCLUDED
22 
23 #include <boost/container/flat_map.hpp>
24 #include <condition_variable>
25 #include <functional>
26 #include <memory>
27 #include <mutex>
28 #include <stdexcept>
29 #include <type_traits>
30 #include <utility>
31 
32 namespace ripple {
33 
35 class io_list final
36 {
37 public:
38  class work
39  {
40  template <class = void>
41  void
42  destroy();
43 
44  friend class io_list;
45  io_list* ios_ = nullptr;
46 
47  public:
48  virtual ~work()
49  {
50  destroy();
51  }
52 
59  io_list&
60  ios()
61  {
62  return *ios_;
63  }
64 
65  virtual void
66  close() = 0;
67  };
68 
69 private:
70  template <class = void>
71  void
72  destroy();
73 
76  bool closed_ = false;
78  boost::container::flat_map<work*, std::weak_ptr<work>> map_;
79  std::function<void(void)> f_;
80 
81 public:
82  io_list() = default;
83 
93  {
94  destroy();
95  }
96 
103  bool
104  closed() const
105  {
106  return closed_;
107  }
108 
127  template <class T, class... Args>
129  emplace(Args&&... args);
130 
149  template <class Finisher>
150  void
151  close(Finisher&& f);
152 
153  void
155  {
156  close([] {});
157  }
158 
173  template <class = void>
174  void
175  join();
176 };
177 
178 //------------------------------------------------------------------------------
179 
180 template <class>
181 void
183 {
184  if (!ios_)
185  return;
186  std::function<void(void)> f;
187  {
188  std::lock_guard lock(ios_->m_);
189  ios_->map_.erase(this);
190  if (--ios_->n_ == 0 && ios_->closed_)
191  {
192  std::swap(f, ios_->f_);
193  ios_->cv_.notify_all();
194  }
195  }
196  if (f)
197  f();
198 }
199 
200 template <class>
201 void
203 {
204  close();
205  join();
206 }
207 
208 template <class T, class... Args>
210 io_list::emplace(Args&&... args)
211 {
212  static_assert(
213  std::is_base_of<work, T>::value, "T must derive from io_list::work");
214  if (closed_)
215  return nullptr;
216  auto sp = std::make_shared<T>(std::forward<Args>(args)...);
217  decltype(sp) dead;
218 
219  std::lock_guard lock(m_);
220  if (!closed_)
221  {
222  ++n_;
223  sp->work::ios_ = this;
224  map_.emplace(sp.get(), sp);
225  }
226  else
227  {
228  std::swap(sp, dead);
229  }
230  return sp;
231 }
232 
233 template <class Finisher>
234 void
235 io_list::close(Finisher&& f)
236 {
238  if (closed_)
239  return;
240  closed_ = true;
241  auto map = std::move(map_);
242  if (!map.empty())
243  {
244  f_ = std::forward<Finisher>(f);
245  lock.unlock();
246  for (auto const& p : map)
247  if (auto sp = p.second.lock())
248  sp->close();
249  }
250  else
251  {
252  lock.unlock();
253  f();
254  }
255 }
256 
257 template <class>
258 void
260 {
262  cv_.wait(lock, [&] { return closed_ && n_ == 0; });
263 }
264 
265 } // namespace ripple
266 
267 #endif
ripple::io_list::close
void close()
Definition: io_list.h:154
std::shared_ptr
STL class.
utility
ripple::io_list::work::~work
virtual ~work()
Definition: io_list.h:48
ripple::io_list::closed_
bool closed_
Definition: io_list.h:76
functional
ripple::io_list::work::destroy
void destroy()
Definition: io_list.h:182
ripple::io_list::destroy
void destroy()
Definition: io_list.h:202
ripple::io_list::io_list
io_list()=default
ripple::io_list::~io_list
~io_list()
Destroy the list.
Definition: io_list.h:92
ripple::io_list::map_
boost::container::flat_map< work *, std::weak_ptr< work > > map_
Definition: io_list.h:78
std::lock_guard
STL class.
ripple::io_list::emplace
std::shared_ptr< T > emplace(Args &&... args)
Create associated work if not closed.
Definition: io_list.h:210
ripple::io_list::work::ios
io_list & ios()
Return the io_list associated with the work.
Definition: io_list.h:60
std::function
ripple::io_list::work::close
virtual void close()=0
stdexcept
ripple::io_list::f_
std::function< void(void)> f_
Definition: io_list.h:79
ripple::io_list::cv_
std::condition_variable cv_
Definition: io_list.h:77
std::unique_lock
STL class.
ripple::io_list::work
Definition: io_list.h:38
std::condition_variable::wait
T wait(T... args)
ripple::io_list::m_
std::mutex m_
Definition: io_list.h:74
memory
ripple::io_list::work::ios_
io_list * ios_
Definition: io_list.h:45
std::swap
T swap(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::io_list::join
void join()
Block until the io_list stops.
Definition: io_list.h:259
condition_variable
mutex
std::size_t
ripple::io_list::n_
std::size_t n_
Definition: io_list.h:75
ripple::io_list::closed
bool closed() const
Return true if the list is closed.
Definition: io_list.h:104
ripple::io_list
Manages a set of objects performing asynchronous I/O.
Definition: io_list.h:35
type_traits
std::condition_variable::notify_all
T notify_all(T... args)
std::is_base_of