/* Specifies a time deadline (C) 2015-2017 Niall Douglas (4 commits) File Created: Dec 2015 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 in the accompanying file Licence.txt or 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. Distributed under the Boost Software License, Version 1.0. (See accompanying file Licence.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #ifndef LLFIO_DEADLINE_H #define LLFIO_DEADLINE_H #include // NOLINT #include // NOLINT //! \file deadline.h Provides struct deadline #if defined(__cplusplus) || DOXYGEN_IS_IN_THE_HOUSE #ifndef LLFIO_CONFIG_HPP #error You must include the master llfio.hpp, not individual header files directly #endif #include "config.hpp" #include LLFIO_V2_NAMESPACE_EXPORT_BEGIN #define LLFIO_DEADLINE_NAME deadline #else #define LLFIO_DEADLINE_NAME boost_llfio_deadline #endif /*! \struct deadline \brief A time deadline in either relative-to-now or absolute (system clock) terms */ struct LLFIO_DEADLINE_NAME { //! True if deadline does not change with system clock changes bool steady; // NOLINT union { //! System time from timespec_get(&ts, TIME_UTC) struct timespec utc; // NOLINT //! Nanosecond ticks from start of operation unsigned long long nsecs; // NOLINT }; #ifdef __cplusplus constexpr deadline() // NOLINT : steady(false), utc{0, 0} { } //! True if deadline is valid constexpr explicit operator bool() const noexcept { return steady || utc.tv_sec != 0; } //! Implicitly construct a deadline from a system clock time point deadline(std::chrono::system_clock::time_point tp) // NOLINT : steady(false), utc{0, 0} { std::chrono::seconds secs(std::chrono::system_clock::to_time_t(tp)); utc.tv_sec = secs.count(); std::chrono::system_clock::time_point _tp(std::chrono::system_clock::from_time_t(utc.tv_sec)); utc.tv_nsec = static_cast(std::chrono::duration_cast(tp - _tp).count()); } //! Implicitly construct a deadline from a duration from now template constexpr deadline(std::chrono::duration d) // NOLINT : steady(true), nsecs(0) { std::chrono::nanoseconds _nsecs = std::chrono::duration_cast(d); // Negative durations are zero duration if(_nsecs.count() > 0) { nsecs = _nsecs.count(); } else { nsecs = 0; } } //! Returns a system_clock::time_point for this deadline std::chrono::system_clock::time_point to_time_point() const { if(steady) { throw std::invalid_argument("Not a UTC deadline!"); // NOLINT } std::chrono::system_clock::time_point tp(std::chrono::system_clock::from_time_t(utc.tv_sec)); tp += std::chrono::duration_cast(std::chrono::nanoseconds(utc.tv_nsec)); return tp; } #endif }; #define LLFIO_DEADLINE_TO_PARTIAL_DEADLINE(nd, d) \ if(d) \ { \ if((d).steady) \ { \ (nd).steady = true; \ std::chrono::nanoseconds ns = std::chrono::duration_cast((began_steady + std::chrono::nanoseconds((d).nsecs)) - std::chrono::steady_clock::now()); \ if(ns.count() < 0) \ (nd).nsecs = 0; \ else \ (nd).nsecs = ns.count(); \ } \ else \ (nd) = (d); \ } #undef LLFIO_DEADLINE_NAME #if defined(__cplusplus) || DOXYGEN_IS_IN_THE_HOUSE LLFIO_V2_NAMESPACE_END #endif #endif