Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
platform_timer_macos.cpp
Go to the documentation of this file.
3
4#include <fc/time.hpp>
5#include <fc/fwd_impl.hpp>
7#include <fc/log/logger_config.hpp> //set_os_thread_name()
8
9#include <mutex>
10#include <thread>
11
12#include <sys/event.h>
13
14namespace sysio { namespace chain {
15
16//a kqueue & thread is shared for all platform_timer_macos instances
17static std::mutex timer_ref_mutex;
18static unsigned next_timerid;
19static unsigned refcount;
20static int kqueue_fd;
21static std::thread kevent_thread;
22
23struct platform_timer::impl {
25
26 constexpr static uint64_t quit_event_id = 1;
27};
28
30 static_assert(sizeof(impl) <= fwd_size);
31
32 std::lock_guard guard(timer_ref_mutex);
33
34 if(refcount++ == 0) {
35 kqueue_fd = kqueue();
36
37 FC_ASSERT(kqueue_fd != -1, "failed to create kqueue");
38
39 //set up a EVFILT_USER which will be signaled to shut down the thread
40 struct kevent64_s quit_event;
41 EV_SET64(&quit_event, impl::quit_event_id, EVFILT_USER, EV_ADD|EV_ENABLE, NOTE_FFNOP, 0, 0, 0, 0);
42 FC_ASSERT(kevent64(kqueue_fd, &quit_event, 1, NULL, 0, KEVENT_FLAG_IMMEDIATE, NULL) == 0, "failed to create quit event");
43
44 kevent_thread = std::thread([]() {
45 fc::set_os_thread_name("checktime");
46 while(true) {
47 struct kevent64_s anEvent;
48 int c = kevent64(kqueue_fd, NULL, 0, &anEvent, 1, 0, NULL);
49
50 if(c == 1 && anEvent.filter == EVFILT_TIMER) {
51 platform_timer* self = (platform_timer*)anEvent.udata;
52 self->expired = 1;
53 self->call_expiration_callback();
54 }
55 else if(c == 1 && anEvent.filter == EVFILT_USER)
56 return;
57 else if(c == -1 && errno == EINTR)
58 continue;
59 else if(c == -1)
60 return; //?? not much we can do now
61 }
62 });
63 }
64
65 my->timerid = next_timerid++;
66
68}
69
71 stop();
72 if(std::lock_guard guard(timer_ref_mutex); --refcount == 0) {
73 struct kevent64_s signal_quit_event;
74 EV_SET64(&signal_quit_event, impl::quit_event_id, EVFILT_USER, 0, NOTE_TRIGGER, 0, 0, 0, 0);
75
76 if(kevent64(kqueue_fd, &signal_quit_event, 1, NULL, 0, KEVENT_FLAG_IMMEDIATE, NULL) != -1)
77 kevent_thread.join();
78 close(kqueue_fd);
79 }
80}
81
83 if(tp == fc::time_point::maximum()) {
84 expired = 0;
85 return;
86 }
88 if(x.count() <= 0)
89 expired = 1;
90 else {
91 struct kevent64_s aTimerEvent;
92 EV_SET64(&aTimerEvent, my->timerid, EVFILT_TIMER, EV_ADD|EV_ENABLE|EV_ONESHOT, NOTE_USECONDS|NOTE_CRITICAL, x.count(), (uint64_t)this, 0, 0);
93
94 expired = 0;
95 if(kevent64(kqueue_fd, &aTimerEvent, 1, NULL, 0, KEVENT_FLAG_IMMEDIATE, NULL) != 0)
96 expired = 1;
97 }
98}
99
101 if(expired)
102 return;
103
104 struct kevent64_s stop_timer_event;
105 EV_SET64(&stop_timer_event, my->timerid, EVFILT_TIMER, EV_DELETE, 0, 0, 0, 0, 0);
106 kevent64(kqueue_fd, &stop_timer_event, 1, NULL, 0, KEVENT_FLAG_IMMEDIATE, NULL);
107 expired = 1;
108}
109
110}}
constexpr int64_t count() const
Definition time.hpp:26
static time_point now()
Definition time.cpp:14
constexpr const microseconds & time_since_epoch() const
Definition time.hpp:52
static constexpr time_point maximum()
Definition time.hpp:46
Defines exception's used by fc.
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
void close(T *e, websocketpp::connection_hdl hdl)
void set_os_thread_name(const string &name)
void compute_and_print_timer_accuracy(platform_timer &t)
@ self
the connection is to itself
Definition protocol.hpp:48
unsigned __int64 uint64_t
Definition stdint.h:136