diff --git a/Builds/CMake/RippledCore.cmake b/Builds/CMake/RippledCore.cmake index 1378d4c3f2..f01d7308e3 100644 --- a/Builds/CMake/RippledCore.cmake +++ b/Builds/CMake/RippledCore.cmake @@ -19,6 +19,7 @@ endif () TODO: review these sources for removal or replacement #]===============================] target_sources (xrpl_core PRIVATE + src/ripple/beast/clock/basic_seconds_clock.cpp src/ripple/beast/core/CurrentThreadName.cpp src/ripple/beast/core/SemanticVersion.cpp src/ripple/beast/hash/impl/xxhash.cpp diff --git a/src/ripple/basics/chrono.h b/src/ripple/basics/chrono.h index aa2ddc7e7c..e0403bed78 100644 --- a/src/ripple/basics/chrono.h +++ b/src/ripple/basics/chrono.h @@ -20,6 +20,8 @@ #ifndef RIPPLE_BASICS_CHRONO_H_INCLUDED #define RIPPLE_BASICS_CHRONO_H_INCLUDED +#include + #include #include #include @@ -85,9 +87,9 @@ using TestStopwatch = beast::manual_clock; inline Stopwatch& stopwatch() { - return beast::get_abstract_clock< - std::chrono::steady_clock, - beast::basic_seconds_clock>(); + using Clock = beast::basic_seconds_clock; + using Facade = Clock::Clock; + return beast::get_abstract_clock(); } } // namespace ripple diff --git a/src/ripple/beast/clock/basic_seconds_clock.cpp b/src/ripple/beast/clock/basic_seconds_clock.cpp new file mode 100644 index 0000000000..c1c97cb7d4 --- /dev/null +++ b/src/ripple/beast/clock/basic_seconds_clock.cpp @@ -0,0 +1,102 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2021, Howard Hinnant + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include + +#include +#include +#include +#include +#include + +namespace beast { + +namespace { + +// Updates the clock +class seconds_clock_thread +{ + using Clock = basic_seconds_clock::Clock; + + bool stop_; + std::mutex mut_; + std::condition_variable cv_; + std::thread thread_; + Clock::time_point tp_; + +public: + ~seconds_clock_thread(); + seconds_clock_thread(); + + Clock::time_point + now(); + +private: + void + run(); +}; + +seconds_clock_thread::~seconds_clock_thread() +{ + assert(thread_.joinable()); + { + std::lock_guard lock(mut_); + stop_ = true; + } // publish stop_ asap so if waiting thread times-out, it will see it + cv_.notify_one(); + thread_.join(); +} + +seconds_clock_thread::seconds_clock_thread() : stop_{false}, tp_{Clock::now()} +{ + thread_ = std::thread(&seconds_clock_thread::run, this); +} + +seconds_clock_thread::Clock::time_point +seconds_clock_thread::now() +{ + std::lock_guard lock(mut_); + return tp_; +} + +void +seconds_clock_thread::run() +{ + std::unique_lock lock(mut_); + while (true) + { + using namespace std::chrono; + + tp_ = Clock::now(); + auto const when = floor(tp_) + 1s; + if (cv_.wait_until(lock, when, [this] { return stop_; })) + return; + } +} + +} // unnamed namespace + +basic_seconds_clock::time_point +basic_seconds_clock::now() +{ + static seconds_clock_thread clk; + return clk.now(); +} + +} // namespace beast diff --git a/src/ripple/beast/clock/basic_seconds_clock.h b/src/ripple/beast/clock/basic_seconds_clock.h index 9c742ece97..4e444fefee 100644 --- a/src/ripple/beast/clock/basic_seconds_clock.h +++ b/src/ripple/beast/clock/basic_seconds_clock.h @@ -20,120 +20,10 @@ #ifndef BEAST_CHRONO_BASIC_SECONDS_CLOCK_H_INCLUDED #define BEAST_CHRONO_BASIC_SECONDS_CLOCK_H_INCLUDED -#include - -#include #include -#include -#include -#include -#include namespace beast { -namespace detail { - -class seconds_clock_worker -{ -public: - virtual void - sample() = 0; - virtual ~seconds_clock_worker() = default; - seconds_clock_worker() = default; - seconds_clock_worker(seconds_clock_worker const&) = delete; - seconds_clock_worker& - operator=(seconds_clock_worker const&) = delete; -}; - -//------------------------------------------------------------------------------ - -// Updates the clocks -class seconds_clock_thread -{ -public: - using mutex = std::mutex; - using cond_var = std::condition_variable; - using unique_lock = std::unique_lock; - using clock_type = std::chrono::steady_clock; - using seconds = std::chrono::seconds; - using thread = std::thread; - using workers = std::vector; - - bool stop_; - mutex mutex_; - cond_var cond_; - workers workers_; - thread thread_; - - seconds_clock_thread() : stop_(false) - { - thread_ = thread(&seconds_clock_thread::run, this); - } - - ~seconds_clock_thread() - { - stop(); - } - - void - add(seconds_clock_worker& w) - { - std::lock_guard lock(mutex_); - workers_.push_back(&w); - } - - void - remove(seconds_clock_worker& w) - { - std::lock_guard lock(mutex_); - workers_.erase(std::find(workers_.begin(), workers_.end(), &w)); - } - - void - stop() - { - if (thread_.joinable()) - { - { - std::lock_guard lock(mutex_); - stop_ = true; - } - cond_.notify_all(); - thread_.join(); - } - } - - void - run() - { - unique_lock lock(mutex_); - ; - - for (;;) - { - for (auto iter : workers_) - iter->sample(); - - using namespace std::chrono; - clock_type::time_point const when( - date::floor(clock_type::now().time_since_epoch()) + - seconds(1)); - - if (cond_.wait_until(lock, when, [this] { return stop_; })) - return; - } - } - - static seconds_clock_thread& - instance() - { - static seconds_clock_thread singleton; - return singleton; - } -}; - -} // namespace detail - /** A clock whose minimum resolution is one second. The purpose of this class is to optimize the performance of the now() @@ -143,10 +33,11 @@ public: @tparam Clock A type meeting these requirements: http://en.cppreference.com/w/cpp/concept/Clock */ -template class basic_seconds_clock { public: + using Clock = std::chrono::steady_clock; + explicit basic_seconds_clock() = default; using rep = typename Clock::rep; @@ -157,54 +48,7 @@ public: static bool const is_steady = Clock::is_steady; static time_point - now() - { - // Make sure the thread is constructed before the - // worker otherwise we will crash during destruction - // of objects with static storage duration. - struct initializer - { - initializer() - { - detail::seconds_clock_thread::instance(); - } - }; - static initializer init; - - struct worker : detail::seconds_clock_worker - { - time_point m_now; - std::mutex mutex_; - - worker() : m_now(Clock::now()) - { - detail::seconds_clock_thread::instance().add(*this); - } - - ~worker() - { - detail::seconds_clock_thread::instance().remove(*this); - } - - time_point - now() - { - std::lock_guard lock(mutex_); - return m_now; - } - - void - sample() override - { - std::lock_guard lock(mutex_); - m_now = Clock::now(); - } - }; - - static worker w; - - return w.now(); - } + now(); }; } // namespace beast diff --git a/src/test/beast/beast_basic_seconds_clock_test.cpp b/src/test/beast/beast_basic_seconds_clock_test.cpp index 7910cc8362..5e55aab598 100644 --- a/src/test/beast/beast_basic_seconds_clock_test.cpp +++ b/src/test/beast/beast_basic_seconds_clock_test.cpp @@ -29,7 +29,7 @@ public: void run() override { - basic_seconds_clock::now(); + basic_seconds_clock::now(); pass(); } }; diff --git a/src/test/nodestore/import_test.cpp b/src/test/nodestore/import_test.cpp index 0bea361ee7..585c4bd91f 100644 --- a/src/test/nodestore/import_test.cpp +++ b/src/test/nodestore/import_test.cpp @@ -106,7 +106,7 @@ pretty_time(std::ostream& os, std::chrono::duration d) else { // use integral - os << date::round(d).count(); + os << round(d).count(); } os << "ns"; } @@ -122,7 +122,7 @@ pretty_time(std::ostream& os, std::chrono::duration d) else { // use integral - os << date::round(d).count(); + os << round(d).count(); } os << "us"; } @@ -138,7 +138,7 @@ pretty_time(std::ostream& os, std::chrono::duration d) else { // use integral - os << date::round(d).count(); + os << round(d).count(); } os << "ms"; } @@ -154,7 +154,7 @@ pretty_time(std::ostream& os, std::chrono::duration d) else { // use integral - os << date::round(d).count(); + os << round(d).count(); } os << "s"; } @@ -170,7 +170,7 @@ pretty_time(std::ostream& os, std::chrono::duration d) else { // use integral - os << date::round(d).count(); + os << round(d).count(); } os << "min"; } @@ -193,7 +193,7 @@ fmtdur(std::chrono::duration const& d) class progress { private: - using clock_type = beast::basic_seconds_clock; + using clock_type = beast::basic_seconds_clock; std::size_t const work_; clock_type::time_point start_ = clock_type::now();