/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright 2018 Danny Robson */ #include "flag.hpp" #include "../cast.hpp" #include #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); }