diff --git a/libraries/chain/platform_timer_asio_fallback.cpp b/libraries/chain/platform_timer_asio_fallback.cpp index 7ec808e128..b82552e412 100644 --- a/libraries/chain/platform_timer_asio_fallback.cpp +++ b/libraries/chain/platform_timer_asio_fallback.cpp @@ -57,36 +57,40 @@ platform_timer::~platform_timer() { void platform_timer::start(fc::time_point tp) { if(tp == fc::time_point::maximum()) { - expired = 0; + expired = false; return; } fc::microseconds x = tp.time_since_epoch() - fc::time_point::now().time_since_epoch(); if(x.count() <= 0) - expired = 1; + expired = true; else { #if 0 std::promise p; auto f = p.get_future(); checktime_ios->post([&p,this]() { - expired = 0; + expired = false; p.set_value(); }); f.get(); #endif - expired = 0; + expired = false; my->timer->expires_after(std::chrono::microseconds(x.count())); my->timer->async_wait([this](const boost::system::error_code& ec) { if(ec) return; - expired = 1; - call_expiration_callback(); + bool expected = false; + if (expired.compare_exchange_strong(expected, true)) { + call_expiration_callback(); + } }); } } void platform_timer::expire_now() { - expired = 1; - call_expiration_callback(); + bool expected = false; + if (expired.compare_exchange_strong(expected, true)) { + call_expiration_callback(); + } } void platform_timer::stop() { @@ -94,7 +98,7 @@ void platform_timer::stop() { return; my->timer->cancel(); - expired = 1; + expired = true; } }} diff --git a/libraries/chain/platform_timer_kqueue.cpp b/libraries/chain/platform_timer_kqueue.cpp index 3e9dc68104..823428c804 100644 --- a/libraries/chain/platform_timer_kqueue.cpp +++ b/libraries/chain/platform_timer_kqueue.cpp @@ -58,8 +58,10 @@ platform_timer::platform_timer() { if(c == 1 && anEvent.filter == EVFILT_TIMER) { platform_timer* self = (platform_timer*)anEvent.udata; - self->expired = 1; - self->call_expiration_callback(); + bool expected = false; + if (self->expired.compare_exchange_strong(expected, true)) { + self->call_expiration_callback(); + } } else if(c == 1 && anEvent.filter == EVFILT_USER) return; @@ -90,25 +92,27 @@ platform_timer::~platform_timer() { void platform_timer::start(fc::time_point tp) { if(tp == fc::time_point::maximum()) { - expired = 0; + expired = false; return; } fc::microseconds x = tp.time_since_epoch() - fc::time_point::now().time_since_epoch(); if(x.count() <= 0) - expired = 1; + expired = true; else { struct kevent64_s aTimerEvent; EV_SET64(&aTimerEvent, my->timerid, EVFILT_TIMER, EV_ADD|EV_ENABLE|EV_ONESHOT, NOTE_USECONDS|NOTE_CRITICAL, x.count(), (uint64_t)this, 0, 0); - expired = 0; + expired = false; if(kevent64(kqueue_fd, &aTimerEvent, 1, NULL, 0, KEVENT_FLAG_IMMEDIATE, NULL) != 0) - expired = 1; + expired = true; } } void platform_timer::expire_now() { - expired = 1; - call_expiration_callback(); + bool expected = false; + if (expired.compare_exchange_strong(expected, true)) { + call_expiration_callback(); + } } void platform_timer::stop() { @@ -118,7 +122,7 @@ void platform_timer::stop() { struct kevent64_s stop_timer_event; EV_SET64(&stop_timer_event, my->timerid, EVFILT_TIMER, EV_DELETE, 0, 0, 0, 0, 0); kevent64(kqueue_fd, &stop_timer_event, 1, NULL, 0, KEVENT_FLAG_IMMEDIATE, NULL); - expired = 1; + expired = true; } }} diff --git a/libraries/chain/platform_timer_posix.cpp b/libraries/chain/platform_timer_posix.cpp index 0a50ebcade..3702333c32 100644 --- a/libraries/chain/platform_timer_posix.cpp +++ b/libraries/chain/platform_timer_posix.cpp @@ -5,12 +5,14 @@ #include #include +#include #include #include #include +#include -namespace eosio { namespace chain { +namespace eosio::chain { static_assert(std::atomic_bool::is_always_lock_free, "Only lock-free atomics AS-safe."); @@ -19,8 +21,10 @@ struct platform_timer::impl { static void sig_handler(int, siginfo_t* si, void*) { platform_timer* self = (platform_timer*)si->si_value.sival_ptr; - self->expired = 1; - self->call_expiration_callback(); + bool expected = false; + if (self->expired.compare_exchange_strong(expected, true)) { + self->call_expiration_callback(); + } } }; @@ -28,9 +32,9 @@ platform_timer::platform_timer() { static_assert(sizeof(impl) <= fwd_size); static bool initialized; - static std::mutex initalized_mutex; + static std::mutex initialized_mutex; - if(std::lock_guard guard(initalized_mutex); !initialized) { + if(std::lock_guard guard(initialized_mutex); !initialized) { struct sigaction act; sigemptyset(&act.sa_mask); act.sa_sigaction = impl::sig_handler; @@ -55,25 +59,27 @@ platform_timer::~platform_timer() { void platform_timer::start(fc::time_point tp) { if(tp == fc::time_point::maximum()) { - expired = 0; + expired = false; return; } fc::microseconds x = tp.time_since_epoch() - fc::time_point::now().time_since_epoch(); if(x.count() <= 0) - expired = 1; + expired = true; else { time_t secs = x.count() / 1000000; long nsec = (x.count() - (secs*1000000)) * 1000; struct itimerspec enable = {{0, 0}, {secs, nsec}}; - expired = 0; + expired = false; if(timer_settime(my->timerid, 0, &enable, NULL) != 0) - expired = 1; + expired = true; } } void platform_timer::expire_now() { - expired = 1; - call_expiration_callback(); + bool expected = false; + if (expired.compare_exchange_strong(expected, true)) { + call_expiration_callback(); + } } void platform_timer::stop() { @@ -81,7 +87,7 @@ void platform_timer::stop() { return; struct itimerspec disable = {{0, 0}, {0, 0}}; timer_settime(my->timerid, 0, &disable, NULL); - expired = 1; + expired = true; } -}} +}