OpenCBDC Transaction Processor
Loading...
Searching...
No Matches
kqueue_event_handler.cpp
Go to the documentation of this file.
1// Copyright (c) 2022 MIT Digital Currency Initiative,
2// Federal Reserve Bank of Boston
3// Distributed under the MIT software license, see the accompanying
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
7
8#include <algorithm>
9#include <array>
10#include <iostream>
11#include <unistd.h>
12
13namespace cbdc::rpc {
17
19 m_kq = kqueue();
20 return m_kq != -1;
21 }
22
23 void kqueue_event_handler::set_timeout(long timeout_ms) {
24 if(timeout_ms == -1) {
25 m_timeout_enabled = false;
26 m_timeout_ms = 1000;
27 return;
28 }
29 m_timeout_enabled = true;
30 m_timeout_ms = timeout_ms;
31 }
32
34 switch(et) {
35 case event_type::remove: {
36 struct kevent ev {};
37 EV_SET(&ev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
38 m_evs.emplace_back(std::move(ev));
39 }
40 {
41 struct kevent ev {};
42 EV_SET(&ev, fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0);
43 m_evs.emplace_back(std::move(ev));
44 }
45 break;
46 case event_type::inout: {
47 struct kevent ev {};
48 EV_SET(&ev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
49 m_evs.emplace_back(std::move(ev));
50 }
51 {
52 struct kevent ev {};
53 EV_SET(&ev, fd, EVFILT_WRITE, EV_ADD, 0, 0, 0);
54 m_evs.emplace_back(std::move(ev));
55 }
56 break;
57 case event_type::in: {
58 struct kevent ev {};
59 EV_SET(&ev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
60 m_evs.emplace_back(std::move(ev));
61 } break;
62 case event_type::out: {
63 struct kevent ev {};
64 EV_SET(&ev, fd, EVFILT_WRITE, EV_ADD, 0, 0, 0);
65 m_evs.emplace_back(std::move(ev));
66 } break;
67 }
68 }
69
70 auto kqueue_event_handler::poll() -> std::optional<std::vector<event>> {
71 auto timeout = timespec{};
72 timeout.tv_sec = m_timeout_ms / 1000;
73 timeout.tv_nsec = (m_timeout_ms % 1000) * 1000000;
74 auto sz = std::max(1UL, m_evs.size());
75 auto evs = std::vector<struct kevent>(sz);
76 auto start_time = std::chrono::high_resolution_clock::now();
77 auto nev = kevent(m_kq,
78 m_evs.data(),
79 static_cast<int>(m_evs.size()),
80 evs.data(),
81 static_cast<int>(evs.size()),
82 &timeout);
83 m_evs.clear();
84 if(nev == -1) {
85 perror("kevent");
86 return std::nullopt;
87 }
88
89 auto ret = std::vector<event>();
90
91 if(m_timeout_enabled) {
92 auto end_time = std::chrono::high_resolution_clock::now();
93 if(end_time - start_time > std::chrono::milliseconds(m_timeout_ms)
94 && nev == 0) {
95 ret.emplace_back(0, true);
96 m_timeout_enabled = false;
97 m_timeout_ms = 1000;
98 }
99 }
100
101 for(size_t i = 0; i < static_cast<size_t>(nev); i++) {
102 auto& ev = evs[i];
103 if(ev.flags & EV_ERROR) {
104 continue;
105 }
106 ret.emplace_back(ev.ident, false);
107 }
108
109 return ret;
110 }
111}
event_type
Type of event to register interest in.
@ remove
Remove file descriptor.
@ inout
Read and write events.
void register_fd(int fd, event_type et) override
Registers a file descriptor to track for events.
auto init() -> bool override
Initializes the event handler.
void set_timeout(long timeout_ms) override
Sets the timeout for poll to return even if there are no events.
auto poll() -> std::optional< std::vector< event > > override
Wait for events on tracked file descriptors.