blob: d7a427ea8773120906636b7ceaca71d469152403 [file] [log] [blame]
Ed Tanouse0d918b2018-03-27 17:41:04 -07001#pragma once
2
Ed Tanouse0d918b2018-03-27 17:41:04 -07003#include <boost/circular_buffer.hpp>
4#include <boost/circular_buffer/space_optimized.hpp>
Ed Tanous1abe55e2018-09-05 08:30:59 -07005#include <chrono>
6#include <functional>
Ed Tanouse0d918b2018-03-27 17:41:04 -07007
Ed Tanousc94ad492019-10-10 15:39:33 -07008#include "logging.h"
Ed Tanous1abe55e2018-09-05 08:30:59 -07009
10namespace crow
11{
12namespace detail
13{
James Feistf0af8592020-03-27 16:28:59 -070014
15constexpr const size_t timerQueueTimeoutSeconds = 5;
16
Ed Tanouse0d918b2018-03-27 17:41:04 -070017// fast timer queue for fixed tick value.
Ed Tanous1abe55e2018-09-05 08:30:59 -070018class TimerQueue
19{
20 public:
21 TimerQueue()
22 {
23 dq.set_capacity(100);
Ed Tanouse0d918b2018-03-27 17:41:04 -070024 }
Ed Tanouse0d918b2018-03-27 17:41:04 -070025
Ed Tanous271584a2019-07-09 16:24:22 -070026 void cancel(size_t k)
Ed Tanous1abe55e2018-09-05 08:30:59 -070027 {
Ed Tanous271584a2019-07-09 16:24:22 -070028 size_t index = k - step;
Ed Tanousb01bf292019-03-25 19:25:26 +000029 if (index < dq.size())
Ed Tanous1abe55e2018-09-05 08:30:59 -070030 {
Ed Tanousb01bf292019-03-25 19:25:26 +000031 dq[index].second = nullptr;
Ed Tanous1abe55e2018-09-05 08:30:59 -070032 }
Ed Tanouse0d918b2018-03-27 17:41:04 -070033 }
Ed Tanouse0d918b2018-03-27 17:41:04 -070034
Ed Tanous271584a2019-07-09 16:24:22 -070035 size_t add(std::function<void()> f)
Ed Tanous1abe55e2018-09-05 08:30:59 -070036 {
37 dq.push_back(
38 std::make_pair(std::chrono::steady_clock::now(), std::move(f)));
Ed Tanous271584a2019-07-09 16:24:22 -070039 size_t ret = step + dq.size() - 1;
Ed Tanouse0d918b2018-03-27 17:41:04 -070040
Ed Tanous1abe55e2018-09-05 08:30:59 -070041 BMCWEB_LOG_DEBUG << "timer add inside: " << this << ' ' << ret;
42 return ret;
43 }
Ed Tanouse0d918b2018-03-27 17:41:04 -070044
Ed Tanous1abe55e2018-09-05 08:30:59 -070045 void process()
46 {
47 auto now = std::chrono::steady_clock::now();
48 while (!dq.empty())
49 {
50 auto& x = dq.front();
Jan Sowinski2b5e08e2020-01-09 17:16:02 +010051 // Check expiration time only for active handlers,
52 // remove canceled ones immediately
Ed Tanous1abe55e2018-09-05 08:30:59 -070053 if (x.second)
54 {
James Feistf0af8592020-03-27 16:28:59 -070055 if (now - x.first <
56 std::chrono::seconds(timerQueueTimeoutSeconds))
Jan Sowinski2b5e08e2020-01-09 17:16:02 +010057 {
58 break;
59 }
60
Ed Tanous1abe55e2018-09-05 08:30:59 -070061 BMCWEB_LOG_DEBUG << "timer call: " << this << ' ' << step;
62 // we know that timer handlers are very simple currenty; call
63 // here
64 x.second();
65 }
66 dq.pop_front();
67 step++;
68 }
69 }
70
71 private:
72 using storage_type =
73 std::pair<std::chrono::time_point<std::chrono::steady_clock>,
74 std::function<void()>>;
75
76 boost::circular_buffer_space_optimized<storage_type,
77 std::allocator<storage_type>>
78 dq{};
79
80 // boost::circular_buffer<storage_type> dq{20};
81 // std::deque<storage_type> dq{};
Ed Tanous271584a2019-07-09 16:24:22 -070082 size_t step{};
Ed Tanouse0d918b2018-03-27 17:41:04 -070083};
Ed Tanous1abe55e2018-09-05 08:30:59 -070084} // namespace detail
85} // namespace crow