blob: bf1e084a0026f08354bc44d872e771bd4ea1e26f [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 Tanous1abe55e2018-09-05 08:30:59 -07008#include "crow/logging.h"
9
10namespace crow
11{
12namespace detail
13{
Ed Tanouse0d918b2018-03-27 17:41:04 -070014// fast timer queue for fixed tick value.
Ed Tanous1abe55e2018-09-05 08:30:59 -070015class TimerQueue
16{
17 public:
18 TimerQueue()
19 {
20 dq.set_capacity(100);
Ed Tanouse0d918b2018-03-27 17:41:04 -070021 }
Ed Tanouse0d918b2018-03-27 17:41:04 -070022
Ed Tanous1abe55e2018-09-05 08:30:59 -070023 void cancel(int k)
24 {
Ed Tanousb01bf292019-03-25 19:25:26 +000025 unsigned int index = static_cast<unsigned int>(k - step);
26 if (index < dq.size())
Ed Tanous1abe55e2018-09-05 08:30:59 -070027 {
Ed Tanousb01bf292019-03-25 19:25:26 +000028 dq[index].second = nullptr;
Ed Tanous1abe55e2018-09-05 08:30:59 -070029 }
Ed Tanouse0d918b2018-03-27 17:41:04 -070030 }
Ed Tanouse0d918b2018-03-27 17:41:04 -070031
Ed Tanous1abe55e2018-09-05 08:30:59 -070032 int add(std::function<void()> f)
33 {
34 dq.push_back(
35 std::make_pair(std::chrono::steady_clock::now(), std::move(f)));
Ed Tanousb01bf292019-03-25 19:25:26 +000036 int ret = step + dq.size() - 1;
Ed Tanouse0d918b2018-03-27 17:41:04 -070037
Ed Tanous1abe55e2018-09-05 08:30:59 -070038 BMCWEB_LOG_DEBUG << "timer add inside: " << this << ' ' << ret;
39 return ret;
40 }
Ed Tanouse0d918b2018-03-27 17:41:04 -070041
Ed Tanous1abe55e2018-09-05 08:30:59 -070042 void process()
43 {
44 auto now = std::chrono::steady_clock::now();
45 while (!dq.empty())
46 {
47 auto& x = dq.front();
48 if (now - x.first < std::chrono::seconds(5))
49 {
50 break;
51 }
52 if (x.second)
53 {
54 BMCWEB_LOG_DEBUG << "timer call: " << this << ' ' << step;
55 // we know that timer handlers are very simple currenty; call
56 // here
57 x.second();
58 }
59 dq.pop_front();
60 step++;
61 }
62 }
63
64 private:
65 using storage_type =
66 std::pair<std::chrono::time_point<std::chrono::steady_clock>,
67 std::function<void()>>;
68
69 boost::circular_buffer_space_optimized<storage_type,
70 std::allocator<storage_type>>
71 dq{};
72
73 // boost::circular_buffer<storage_type> dq{20};
74 // std::deque<storage_type> dq{};
75 int step{};
Ed Tanouse0d918b2018-03-27 17:41:04 -070076};
Ed Tanous1abe55e2018-09-05 08:30:59 -070077} // namespace detail
78} // namespace crow