// -*- C++ -*- header.

// Copyright (C) 2020-2021 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/** @file bits/semaphore_base.h
 *  This is an internal header file, included by other library headers.
 *  Do not attempt to use it directly. @headername{semaphore}
 */

#ifndef _GLIBCXX_SEMAPHORE_BASE_H
#define _GLIBCXX_SEMAPHORE_BASE_H 1

#pragma GCC system_header

#include <bits/atomic_base.h>
#if __cpp_lib_atomic_wait
#include <bits/atomic_timed_wait.h>
#include <ext/numeric_traits.h>
#endif // __cpp_lib_atomic_wait

#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE
# include <exception>	// std::terminate
# include <cerrno>	// errno, EINTR, EAGAIN etc.
# include <limits.h>	// SEM_VALUE_MAX
# include <semaphore.h>	// sem_t, sem_init, sem_wait, sem_post etc.
#endif

#include <chrono>
#include <type_traits>

namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE
  struct __platform_semaphore
  {
    using __clock_t = chrono::system_clock;
#ifdef SEM_VALUE_MAX
    static constexpr ptrdiff_t _S_max = SEM_VALUE_MAX;
#else
    static constexpr ptrdiff_t _S_max = _POSIX_SEM_VALUE_MAX;
#endif

    explicit __platform_semaphore(ptrdiff_t __count) noexcept
    {
      sem_init(&_M_semaphore, 0, __count);
    }

    __platform_semaphore(const __platform_semaphore&) = delete;
    __platform_semaphore& operator=(const __platform_semaphore&) = delete;

    ~__platform_semaphore()
    { sem_destroy(&_M_semaphore); }

    _GLIBCXX_ALWAYS_INLINE void
    _M_acquire() noexcept
    {
      for (;;)
	{
	  auto __err = sem_wait(&_M_semaphore);
	  if (__err && (errno == EINTR))
	    continue;
	  else if (__err)
	    std::terminate();
	  else
	    break;
	}
    }

    _GLIBCXX_ALWAYS_INLINE bool
    _M_try_acquire() noexcept
    {
      for (;;)
	{
	  auto __err = sem_trywait(&_M_semaphore);
	  if (__err && (errno == EINTR))
	    continue;
	  else if (__err && (errno == EAGAIN))
	    return false;
	  else if (__err)
	    std::terminate();
	  else
	    break;
	}
      return true;
    }

    _GLIBCXX_ALWAYS_INLINE void
    _M_release(std::ptrdiff_t __update) noexcept
    {
      for(; __update != 0; --__update)
	{
	   auto __err = sem_post(&_M_semaphore);
	   if (__err)
	     std::terminate();
	}
    }

    bool
    _M_try_acquire_until_impl(const chrono::time_point<__clock_t>& __atime)
      noexcept
    {

      auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
      auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);

      struct timespec __ts =
      {
	static_cast<std::time_t>(__s.time_since_epoch().count()),
	static_cast<long>(__ns.count())
      };

      for (;;)
	{
	  if (auto __err = sem_timedwait(&_M_semaphore, &__ts))
	    {
	      if (errno == EINTR)
		continue;
	      else if (errno == ETIMEDOUT || errno == EINVAL)
		return false;
	      else
		std::terminate();
	    }
	  else
	    break;
	}
      return true;
    }

    template<typename _Clock, typename _Duration>
      bool
      _M_try_acquire_until(const chrono::time_point<_Clock,
			   _Duration>& __atime) noexcept
      {
	if constexpr (std::is_same_v<__clock_t, _Clock>)
	  {
	    return _M_try_acquire_until_impl(__atime);
	  }
	else
	  {
	    const typename _Clock::time_point __c_entry = _Clock::now();
	    const auto __s_entry = __clock_t::now();
	    const auto __delta = __atime - __c_entry;
	    const auto __s_atime = __s_entry + __delta;
	    if (_M_try_acquire_until_impl(__s_atime))
	      return true;

	    // We got a timeout when measured against __clock_t but
	    // we need to check against the caller-supplied clock
	    // to tell whether we should return a timeout.
	    return (_Clock::now() < __atime);
	  }
      }

    template<typename _Rep, typename _Period>
      _GLIBCXX_ALWAYS_INLINE bool
      _M_try_acquire_for(const chrono::duration<_Rep, _Period>& __rtime)
	noexcept
      { return _M_try_acquire_until(__clock_t::now() + __rtime); }

  private:
    sem_t _M_semaphore;
  };
#endif // _GLIBCXX_HAVE_POSIX_SEMAPHORE

#if __cpp_lib_atomic_wait
  struct __atomic_semaphore
  {
    static constexpr ptrdiff_t _S_max = __gnu_cxx::__int_traits<int>::__max;
    explicit __atomic_semaphore(__detail::__platform_wait_t __count) noexcept
      : _M_counter(__count)
    {
      __glibcxx_assert(__count >= 0 && __count <= _S_max);
    }

    __atomic_semaphore(const __atomic_semaphore&) = delete;
    __atomic_semaphore& operator=(const __atomic_semaphore&) = delete;

    static _GLIBCXX_ALWAYS_INLINE bool
    _S_do_try_acquire(__detail::__platform_wait_t* __counter) noexcept
    {
      auto __old = __atomic_impl::load(__counter, memory_order::acquire);
      if (__old == 0)
	return false;

      return __atomic_impl::compare_exchange_strong(__counter,
						    __old, __old - 1,
						    memory_order::acquire,
						    memory_order::relaxed);
    }

    _GLIBCXX_ALWAYS_INLINE void
    _M_acquire() noexcept
    {
      auto const __pred =
	[this] { return _S_do_try_acquire(&this->_M_counter); };
      std::__atomic_wait_address_bare(&_M_counter, __pred);
    }

    bool
    _M_try_acquire() noexcept
    {
      auto const __pred =
	[this] { return _S_do_try_acquire(&this->_M_counter); };
      return std::__detail::__atomic_spin(__pred);
    }

    template<typename _Clock, typename _Duration>
      _GLIBCXX_ALWAYS_INLINE bool
      _M_try_acquire_until(const chrono::time_point<_Clock,
			   _Duration>& __atime) noexcept
      {
	auto const __pred =
	  [this] { return _S_do_try_acquire(&this->_M_counter); };

	return __atomic_wait_address_until_bare(&_M_counter, __pred, __atime);
      }

    template<typename _Rep, typename _Period>
      _GLIBCXX_ALWAYS_INLINE bool
      _M_try_acquire_for(const chrono::duration<_Rep, _Period>& __rtime)
	noexcept
      {
	auto const __pred =
	  [this] { return _S_do_try_acquire(&this->_M_counter); };

	return __atomic_wait_address_for_bare(&_M_counter, __pred, __rtime);
      }

    _GLIBCXX_ALWAYS_INLINE void
    _M_release(ptrdiff_t __update) noexcept
    {
      if (0 < __atomic_impl::fetch_add(&_M_counter, __update, memory_order_release))
	return;
      if (__update > 1)
	__atomic_notify_address_bare(&_M_counter, true);
      else
	__atomic_notify_address_bare(&_M_counter, false);
    }

  private:
    alignas(__detail::__platform_wait_alignment)
    __detail::__platform_wait_t _M_counter;
  };
#endif // __cpp_lib_atomic_wait

// Note: the _GLIBCXX_USE_POSIX_SEMAPHORE macro can be used to force the
// use of Posix semaphores (sem_t). Doing so however, alters the ABI.
#if defined __cpp_lib_atomic_wait && !_GLIBCXX_USE_POSIX_SEMAPHORE
  using __semaphore_impl = __atomic_semaphore;
#elif _GLIBCXX_HAVE_POSIX_SEMAPHORE
  using __semaphore_impl = __platform_semaphore;
#endif

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // _GLIBCXX_SEMAPHORE_BASE_H
