/* * 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 "flag.hpp" #include "../cast.hpp" #include "../posix/except.hpp" #include #include #include #include #include using util::thread::flag; /////////////////////////////////////////////////////////////////////////////// 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); } /////////////////////////////////////////////////////////////////////////////// flag::flag (): value (0) { ; } /////////////////////////////////////////////////////////////////////////////// void flag::wait (void) { if (value) return; while (!value) { auto res = sys_futex (&value, FUTEX_WAIT, 0, nullptr, nullptr, 0); if (res < 0) { switch (errno) { case EAGAIN: return; case EINTR: continue; } posix::error::throw_code (); } } } /////////////////////////////////////////////////////////////////////////////// int flag::notify (void) { return notify (std::numeric_limits::max ()); } //----------------------------------------------------------------------------- int flag::notify (int count) { value = 1; auto res = sys_futex (&value, FUTEX_WAKE, count, nullptr, nullptr, 0); if (res < 0) posix::error::throw_code (); return util::cast::narrow (res); }