2 * Copyright (C) 2012-2021 Euclid Science Ground Segment
4 * This library is free software; you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License as published by the Free
6 * Software Foundation; either version 3.0 of the License, or (at your option)
9 * This library is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20#include <mach/mach_init.h>
21#include <mach/mach_traps.h>
22#include <mach/semaphore.h>
24#include <system_error>
27class Semaphore::SemaphoreImpl {
29 explicit SemaphoreImpl(unsigned int i) {
30 auto ret = semaphore_create(mach_task_self(), &m_semaphore, SYNC_POLICY_FIFO, i);
31 if (ret != KERN_SUCCESS) {
32 throw std::system_error(errno, std::system_category());
37 semaphore_destroy(mach_task_self(), m_semaphore);
41 if (semaphore_signal(m_semaphore) != KERN_SUCCESS) {
42 throw std::system_error(EINVAL, std::system_category());
48 auto ret = semaphore_wait(m_semaphore);
49 if (ret == KERN_SUCCESS) {
52 if (ret == KERN_ABORTED) {
55 throw std::system_error(EINVAL, std::system_category());
60 const mach_timespec_t wait{0, 0};
61 return timed_wait(wait);
64 bool try_acquire_until(std::chrono::system_clock::time_point abs_time) {
65 using std::chrono::duration_cast;
67 auto now = std::chrono::system_clock::now();
68 auto left = abs_time - now;
70 auto seconds = duration_cast<std::chrono::seconds>(left);
71 auto nseconds = duration_cast<std::chrono::nanoseconds>(left) - duration_cast<std::chrono::nanoseconds>(seconds);
73 const mach_timespec_t wait{static_cast<unsigned int>(seconds.count()), static_cast<int>(nseconds.count())};
74 return timed_wait(wait);
78 semaphore_t m_semaphore;
80 bool timed_wait(const mach_timespec_t& wait) {
81 auto ret = semaphore_timedwait(m_semaphore, wait);
82 if (ret == KERN_SUCCESS) {
85 if (ret == KERN_OPERATION_TIMED_OUT) {
88 throw std::system_error(EINVAL, std::system_category());