/* * Copyright (c) Facebook, Inc. and its affiliates. * * 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. */ #pragma once #include #include #include #include #include #include /*** * include or backport: * * std::chrono::ceil * * std::chrono::floor * * std::chrono::round */ #if __cpp_lib_chrono >= 201510 || _LIBCPP_STD_VER > 14 || _MSC_VER namespace folly { namespace chrono { /* using override */ using std::chrono::abs; /* using override */ using std::chrono::ceil; /* using override */ using std::chrono::floor; /* using override */ using std::chrono::round; } // namespace chrono } // namespace folly #else namespace folly { namespace chrono { namespace detail { // from: http://en.cppreference.com/w/cpp/chrono/duration/ceil, CC-BY-SA template struct is_duration : std::false_type {}; template struct is_duration> : std::true_type {}; template constexpr To ceil_impl(Duration const& d, To const& t) { return t < d ? t + To{1} : t; } template constexpr To floor_impl(Duration const& d, To const& t) { return t > d ? t - To{1} : t; } template constexpr To round_impl(To const& t0, To const& t1, Diff diff0, Diff diff1) { return diff0 < diff1 ? t0 : diff1 < diff0 ? t1 : t0.count() & 1 ? t1 : t0; } template constexpr To round_impl(Duration const& d, To const& t0, To const& t1) { return round_impl(t0, t1, d - t0, t1 - d); } template constexpr To round_impl(Duration const& d, To const& t0) { return round_impl(d, t0, t0 + To{1}); } } // namespace detail // mimic: std::chrono::abs, C++17 template < typename Rep, typename Period, typename = typename std::enable_if< std::chrono::duration::min() < std::chrono::duration::zero()>::type> constexpr std::chrono::duration abs( std::chrono::duration const& d) { return d < std::chrono::duration::zero() ? -d : d; } // mimic: std::chrono::ceil, C++17 // from: http://en.cppreference.com/w/cpp/chrono/duration/ceil, CC-BY-SA template < typename To, typename Rep, typename Period, typename = typename std::enable_if::value>::type> constexpr To ceil(std::chrono::duration const& d) { return detail::ceil_impl(d, std::chrono::duration_cast(d)); } // mimic: std::chrono::ceil, C++17 // from: http://en.cppreference.com/w/cpp/chrono/time_point/ceil, CC-BY-SA template < typename To, typename Clock, typename Duration, typename = typename std::enable_if::value>::type> constexpr std::chrono::time_point ceil( std::chrono::time_point const& tp) { return std::chrono::time_point{ceil(tp.time_since_epoch())}; } // mimic: std::chrono::floor, C++17 // from: http://en.cppreference.com/w/cpp/chrono/duration/floor, CC-BY-SA template < typename To, typename Rep, typename Period, typename = typename std::enable_if::value>::type> constexpr To floor(std::chrono::duration const& d) { return detail::floor_impl(d, std::chrono::duration_cast(d)); } // mimic: std::chrono::floor, C++17 // from: http://en.cppreference.com/w/cpp/chrono/time_point/floor, CC-BY-SA template < typename To, typename Clock, typename Duration, typename = typename std::enable_if::value>::type> constexpr std::chrono::time_point floor( std::chrono::time_point const& tp) { return std::chrono::time_point{floor(tp.time_since_epoch())}; } // mimic: std::chrono::round, C++17 // from: http://en.cppreference.com/w/cpp/chrono/duration/round, CC-BY-SA template < typename To, typename Rep, typename Period, typename = typename std::enable_if< detail::is_duration::value && !std::chrono::treat_as_floating_point::value>::type> constexpr To round(std::chrono::duration const& d) { return detail::round_impl(d, floor(d)); } // mimic: std::chrono::round, C++17 // from: http://en.cppreference.com/w/cpp/chrono/time_point/round, CC-BY-SA template < typename To, typename Clock, typename Duration, typename = typename std::enable_if< detail::is_duration::value && !std::chrono::treat_as_floating_point::value>::type> constexpr std::chrono::time_point round( std::chrono::time_point const& tp) { return std::chrono::time_point{round(tp.time_since_epoch())}; } } // namespace chrono } // namespace folly #endif namespace folly { namespace chrono { struct coarse_steady_clock { using rep = std::chrono::milliseconds::rep; using period = std::chrono::milliseconds::period; using duration = std::chrono::duration; using time_point = std::chrono::time_point; constexpr static bool is_steady = true; static time_point now() noexcept { #ifndef CLOCK_MONOTONIC_COARSE return time_point(std::chrono::duration_cast( std::chrono::steady_clock::now().time_since_epoch())); #else timespec ts; auto ret = clock_gettime(CLOCK_MONOTONIC_COARSE, &ts); if (kIsDebug && (ret != 0)) { throw_exception( "Error using CLOCK_MONOTONIC_COARSE."); } return time_point(std::chrono::duration_cast( std::chrono::seconds(ts.tv_sec) + std::chrono::nanoseconds(ts.tv_nsec))); #endif } }; } // namespace chrono } // namespace folly