/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 2018 Danny Robson */ #include "event.hpp" #include "../cast.hpp" #include "../posix/except.hpp" #include #include #include #include #include using cruft::thread::event; /////////////////////////////////////////////////////////////////////////////// static long sys_futex (void *addr1, int op, int val1, struct timespec *timeout, void *addr2, int val3) { return syscall (SYS_futex, addr1, op | FUTEX_PRIVATE_FLAG, val1, timeout, addr2, val3); } /////////////////////////////////////////////////////////////////////////////// event::event (): value (0) { ; } /////////////////////////////////////////////////////////////////////////////// void event::wait (void) { for (auto observed = value.load (); observed == value.load (); ) { auto res = sys_futex (&value, FUTEX_WAIT, observed, nullptr, nullptr, 0); if (res < 0) { switch (errno) { case EAGAIN: return; case EINTR: continue; } posix::error::throw_code (); } } } /////////////////////////////////////////////////////////////////////////////// int event::notify_all (void) { return notify (std::numeric_limits::max ()); } //----------------------------------------------------------------------------- int event::notify (int count) { ++value; auto res = sys_futex (&value, FUTEX_WAKE, count, nullptr, nullptr, 0); if (res < 0) posix::error::throw_code (); return cruft::cast::narrow (res); }