Line data Source code
1 : /**
2 : * @file TimestampEstimatorBase.cpp
3 : *
4 : * This is part of the DUNE DAQ Software Suite, copyright 2020.
5 : * Licensing/copyright details are in the COPYING file that you should have
6 : * received with this code.
7 : */
8 :
9 : #include "utilities/TimestampEstimatorBase.hpp"
10 :
11 : #include <thread>
12 :
13 : namespace dunedaq::utilities {
14 :
15 : /**
16 : * @brief Waits for a valid timestamp to become available. Returns a status value that
17 : * indicates whether a valid timestamp is available or not.
18 : * @param continue_flag whether to continue waiting until a valid timestamp is available
19 : * or return immediately
20 : * @param last_seen_ts (Output parameter) the last timestamp seen by the method
21 : * @details The value of the continue_flag can be changed from true to false externally
22 : * to this method, and that will cause the method to exit soon thereafter
23 : * (on the order of 10 msec) and return the current status.
24 : * @return kFinished if a valid timestamp is available or kInterrupted if one is not
25 : */
26 : TimestampEstimatorBase::WaitStatus
27 10 : TimestampEstimatorBase::wait_for_valid_timestamp(std::atomic<bool>& continue_flag, uint64_t& last_seen_ts) // NOLINT
28 : {
29 10 : last_seen_ts = s_invalid_ts;
30 10 : auto sleep_time = std::chrono::microseconds(1);
31 : // Always call get_timestamp_estimate at least once
32 95 : while ((last_seen_ts = get_timestamp_estimate()) == s_invalid_ts && continue_flag.load()) {
33 75 : std::this_thread::sleep_for(sleep_time);
34 75 : if (sleep_time < std::chrono::milliseconds(10)) {
35 14 : sleep_time *= 2;
36 : }
37 : }
38 :
39 : // 27-May-2025, KAB: modified this return statement so that the return code is based on whether a
40 : // valid timestamp is available (instead of whether the caller asked the method to wait or not)
41 10 : return (last_seen_ts != s_invalid_ts) ? TimestampEstimatorBase::kFinished : TimestampEstimatorBase::kInterrupted;
42 : }
43 :
44 : TimestampEstimatorBase::WaitStatus
45 2 : TimestampEstimatorBase::wait_for_requested_timestamp(uint64_t ts, // NOLINT(build/unsigned)
46 : std::atomic<bool>& continue_flag,
47 : uint64_t& last_seen_ts) // NOLINT(build/unsigned)
48 : {
49 2 : last_seen_ts = s_invalid_ts;
50 10 : auto get_sleep_time = [this, ts]() {
51 8 : auto est = get_wait_estimate(ts);
52 8 : auto pest = static_cast<std::chrono::microseconds::rep>(static_cast<double>(est.count()) * 0.8);
53 8 : if (pest < 1 && est != std::chrono::microseconds(0))
54 0 : return std::chrono::microseconds(1);
55 8 : return std::chrono::microseconds(pest);
56 2 : };
57 2 : auto sleep_time = get_sleep_time();
58 : // Always call get_timestamp_estimate at least once
59 8 : while (((last_seen_ts = get_timestamp_estimate()) < ts || last_seen_ts == s_invalid_ts) && continue_flag.load()) {
60 6 : std::this_thread::sleep_for(sleep_time);
61 6 : sleep_time = get_sleep_time();
62 : }
63 2 : return (last_seen_ts >= ts && last_seen_ts != s_invalid_ts) ? TimestampEstimatorBase::kFinished
64 2 : : TimestampEstimatorBase::kInterrupted;
65 : }
66 :
67 : } // namespace dunedaq::utilities
|