blob: a0115dca013a301dc3a124758ff7dd4fcd9d467c [file] [log] [blame]
John Park33858a32018-09-28 23:05:48 -07001#include "aos/event.h"
Brian Silvermanf5f34902015-03-29 17:57:59 -04002
Austin Schuhf2a50ba2016-12-24 16:16:26 -08003#include <chrono>
4
John Park33858a32018-09-28 23:05:48 -07005#include "aos/type_traits/type_traits.h"
6#include "aos/logging/logging.h"
Brian Silvermanf5f34902015-03-29 17:57:59 -04007
8namespace aos {
9
10Event::Event() : impl_(0) {
11 static_assert(shm_ok<Event>::value,
12 "Event is not safe for use in shared memory.");
13}
14
15void Event::Wait() {
Brian Silverman408511d2016-09-10 16:12:02 -040016 while (__atomic_load_n(&impl_, __ATOMIC_SEQ_CST) == 0) {
17 const int ret = futex_wait(&impl_);
18 if (ret != 0) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070019 AOS_CHECK_EQ(-1, ret);
20 AOS_PLOG(FATAL, "futex_wait(%p) failed", &impl_);
Brian Silverman408511d2016-09-10 16:12:02 -040021 }
22 }
Brian Silvermanf5f34902015-03-29 17:57:59 -040023}
24
Austin Schuhf2a50ba2016-12-24 16:16:26 -080025bool Event::WaitTimeout(monotonic_clock::duration timeout) {
26 ::std::chrono::seconds sec =
27 ::std::chrono::duration_cast<::std::chrono::seconds>(timeout);
28 ::std::chrono::nanoseconds nsec =
29 ::std::chrono::duration_cast<::std::chrono::nanoseconds>(timeout - sec);
30 struct timespec timeout_timespec;
31 timeout_timespec.tv_sec = sec.count();
32 timeout_timespec.tv_nsec = nsec.count();
Brian Silverman408511d2016-09-10 16:12:02 -040033 while (true) {
34 if (__atomic_load_n(&impl_, __ATOMIC_SEQ_CST) != 0) {
35 return true;
36 }
37 const int ret = futex_wait_timeout(&impl_, &timeout_timespec);
38 if (ret != 0) {
39 if (ret == 2) return false;
Austin Schuhf257f3c2019-10-27 21:00:43 -070040 AOS_CHECK_EQ(-1, ret);
41 AOS_PLOG(FATAL, "futex_wait(%p) failed", &impl_);
Brian Silverman408511d2016-09-10 16:12:02 -040042 }
43 }
Brian Silverman30608942015-04-08 19:16:46 -040044}
45
Brian Silvermanf5f34902015-03-29 17:57:59 -040046// We're not going to expose the number woken because that's not easily portable
47// to condition variable-based implementations.
48void Event::Set() {
49 if (futex_set(&impl_) == -1) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070050 AOS_PLOG(FATAL, "futex_set(%p) failed", &impl_);
Brian Silvermanf5f34902015-03-29 17:57:59 -040051 }
52}
53
54bool Event::Clear() {
55 return !futex_unset(&impl_);
56}
57
58} // namespace aos