1 //
2 // Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9 
10 #ifndef BOOST_BEAST_CORE_DETAIL_TIMEOUT_SERVICE_HPP
11 #define BOOST_BEAST_CORE_DETAIL_TIMEOUT_SERVICE_HPP
12 
13 #include <boost/beast/core/error.hpp>
14 #include <boost/beast/experimental/core/detail/service_base.hpp>
15 #include <boost/assert.hpp>
16 #include <boost/core/ignore_unused.hpp>
17 #include <boost/asio/bind_executor.hpp>
18 #include <boost/asio/executor.hpp>
19 #include <boost/asio/io_context.hpp>
20 #include <boost/asio/post.hpp>
21 #include <boost/asio/steady_timer.hpp>
22 #include <boost/asio/strand.hpp>
23 #include <chrono>
24 #include <cstdlib>
25 #include <mutex>
26 #include <utility>
27 #include <vector>
28 
29 namespace boost {
30 namespace beast {
31 namespace detail {
32 
33 //------------------------------------------------------------------------------
34 
35 class timeout_service;
36 
37 class timeout_object
38 {
39     friend class timeout_service;
40 
41     using list_type = std::vector<timeout_object*>;
42 
43     timeout_service& svc_;
44     std::size_t pos_;
45     list_type* list_ = nullptr;
46     char outstanding_work_ = 0;
47 
48 public:
49     timeout_object() = delete;
50     timeout_object(timeout_object&&) = delete;
51     timeout_object(timeout_object const&) = delete;
52     timeout_object& operator=(timeout_object&&) = delete;
53     timeout_object& operator=(timeout_object const&) = delete;
54 
55     // VFALCO should be execution_context
56     explicit
57     timeout_object(boost::asio::io_context& ioc);
58 
59     timeout_service&
service() const60     service() const
61     {
62         return svc_;
63     }
64 
65     virtual void on_timeout() = 0;
66 };
67 
68 //------------------------------------------------------------------------------
69 
70 class timeout_service
71     : public service_base<timeout_service>
72 {
73 public:
74     using key_type = timeout_service;
75 
76     // VFALCO Should be execution_context
77     explicit
78     timeout_service(boost::asio::io_context& ctx);
79 
80     void
81     on_work_started(timeout_object& obj);
82 
83     void
84     on_work_complete(timeout_object& obj);
85 
86     void
87     on_work_stopped(timeout_object& obj);
88 
89     void
90     set_option(std::chrono::seconds n);
91 
92 private:
93     friend class timeout_object;
94 
95     using list_type = std::vector<timeout_object*>;
96 
97     void insert(timeout_object& obj, list_type& list);
98     void remove(timeout_object& obj);
99     void do_async_wait();
100     void on_timer(error_code ec);
101 
102     virtual void shutdown() noexcept override;
103 
104     boost::asio::strand<
105         boost::asio::io_context::executor_type> strand_;
106 
107     std::mutex m_;
108     list_type list_[2];
109     list_type* fresh_ = &list_[0];
110     list_type* stale_ = &list_[1];
111     std::size_t count_ = 0;
112     boost::asio::steady_timer timer_;
113     std::chrono::seconds interval_{30ul};
114 };
115 
116 //------------------------------------------------------------------------------
117 
118 } // detail
119 } // beast
120 } // boost
121 
122 #include <boost/beast/experimental/core/detail/impl/timeout_service.ipp>
123 
124 #endif
125