RTC Toolkit  1.0.0
readerHelpers.hpp
Go to the documentation of this file.
1 
12 #ifndef RTCTK_DATATASK_READERHELPERS_HPP
13 #define RTCTK_DATATASK_READERHELPERS_HPP
15 
16 #include <chrono>
17 #include <system_error>
18 #include <cmath>
19 
20 namespace rtctk::dataTask {
25 namespace detail {
26 
27 
37 std::chrono::milliseconds CalcDuration(size_t count, size_t loop_frequency, float error_margin = 1.0)
38 {
39  using namespace std::chrono;
40  return milliseconds{static_cast<int>(ceil(1000.0 * count / loop_frequency))};
41 }
42 
53 std::pair<std::chrono::milliseconds, std::chrono::milliseconds> CalcTimeout(size_t count, \
54  size_t loop_frequency,\
55  float error_margin = 2.0)
56 {
57  using namespace std::chrono;
58 
59  int timeout_total = ceil((static_cast<float>(count)/loop_frequency)*1000)*error_margin;
60  int timeout_short = ceil((static_cast<float>(1)/loop_frequency)*1000)*error_margin;
61  return {milliseconds{timeout_short}, milliseconds{timeout_total}};
62 }
63 
77 template <typename ReaderType, typename Operation>
78 std::error_code Read(ReaderType& reader, Operation&& op, size_t count, size_t loop_frequency, \
79  float error_margin = 2.0)
80 {
82  using namespace std::chrono;
83 
84  auto [timeout_short, timeout_total] = CalcTimeout(count, loop_frequency, error_margin);
85 
86  size_t read = 0;
87  std::error_code const ok;
88  std::pair<std::error_code, size_t> ret;
89  milliseconds time_elapsed {0};
90  auto time_start = system_clock::now();
91 
92  while (1) {
93  ret = reader.Read(std::forward<Operation>(op), count, timeout_short);
94  if(ret.first != ok) {
95  LOG4CPLUS_ERROR(GetLogger(), "Reading from shm timed out: check queue is being filled");
96  LOG4CPLUS_ERROR(GetLogger(), "Read: " << ret.second << " in " << timeout_short.count() << " ms");
97  LOG4CPLUS_ERROR(GetLogger(), "Expected: " << count);
98  return ret.first;
99  }
100  read += ret.second;
101  if (read == count) {
102  return {};
103  }
104 
105  time_elapsed = duration_cast<milliseconds>(system_clock::now() - time_start);
106  if (time_elapsed > timeout_total) {
107  LOG4CPLUS_ERROR(GetLogger(), "Reading from shm timed out: check queue is being filled");
108  LOG4CPLUS_ERROR(GetLogger(), "Read: " << read << " in " << time_elapsed.count() << " ms");
109  LOG4CPLUS_ERROR(GetLogger(), "Expected: " << read);
110  return std::make_error_code(std::errc::timed_out);
111  }
112  }
113 }
114 
115 
116 
128 template <typename ReaderType>
129 std::error_code Skip(ReaderType& reader, size_t count, size_t loop_frequency, \
130  float error_margin = 2.0)
131 {
133  using namespace std::chrono;
134 
135  auto [timeout_short, timeout_total] = CalcTimeout(count, loop_frequency, error_margin);
136 
137  size_t skipped = 0;
138  std::error_code const ok;
139  std::pair<std::error_code, size_t> ret;
140  milliseconds time_elapsed {0};
141  auto time_start = system_clock::now();
142 
143  while (1) {
144  ret = reader.Skip(count, timeout_short);
145  if(ret.first != ok) {
146  LOG4CPLUS_ERROR(GetLogger(), "Reading from shm timed out: check queue is being filled");
147  LOG4CPLUS_ERROR(GetLogger(), "Read: " << ret.second << " in " << timeout_short.count() << " ms");
148  LOG4CPLUS_ERROR(GetLogger(), "Expected: " << count);
149  return ret.first;
150  }
151  skipped += ret.second;
152  if (skipped == count) {
153  return {};
154  }
155 
156  time_elapsed = duration_cast<milliseconds>(system_clock::now() - time_start);
157  if (time_elapsed > timeout_total) {
158  LOG4CPLUS_ERROR(GetLogger(), "Reading from shm timed out: check queue is being filled");
159  LOG4CPLUS_ERROR(GetLogger(), "Read: " << skipped << " in " << time_elapsed.count() << " ms");
160  LOG4CPLUS_ERROR(GetLogger(), "Expected: " << skipped);
161  return std::make_error_code(std::errc::timed_out);
162  }
163  }
164 }
165 
166 
175 template <typename ReaderType>
176 std::error_code Reset(ReaderType& reader)
177 {
178  if (reader.Size() != 0) {
179  return reader.Reset();
180  }
181  return {};
182 }
183 
192 template <typename ReaderType>
193 size_t NumFree(ReaderType& reader)
194 {
195  return reader.Size() - reader.NumAvailable();
196 }
197 
198 } // namespace
199 
200 } // namespace
201 
202 #endif
rtctk::dataTask::detail::CalcDuration
std::chrono::milliseconds CalcDuration(size_t count, size_t loop_frequency, float error_margin=1.0)
free helper function to calulate the estimated time to read the a number of samples at a given freque...
Definition: readerHelpers.hpp:37
rtctk::dataTask::detail::Reset
std::error_code Reset(ReaderType &reader)
helper function to reset the ipcq.reader to latest sample
Definition: readerHelpers.hpp:176
rtctk::dataTask::detail::Read
std::error_code Read(ReaderType &reader, Operation &&op, size_t count, size_t loop_frequency, float error_margin=2.0)
helper function to wrap the ipcq.read with handling of timeouts and count values
Definition: readerHelpers.hpp:78
rtctk::dataTask::detail::Skip
std::error_code Skip(ReaderType &reader, size_t count, size_t loop_frequency, float error_margin=2.0)
helper function to wrap the ipcq.skip with handling of timeouts and count values
Definition: readerHelpers.hpp:129
rtctk::componentFramework::GetLogger
log4cplus::Logger & GetLogger(const std::string &name="")
Get handle to a specific logger (used with logging macros)
rtctk::dataTask::detail::NumFree
size_t NumFree(ReaderType &reader)
helper function to get the free space in the shm.
Definition: readerHelpers.hpp:193
rtctk::dataTask
Definition: messageQueue.hpp:20
rtctk::dataTask::detail::CalcTimeout
std::pair< std::chrono::milliseconds, std::chrono::milliseconds > CalcTimeout(size_t count, size_t loop_frequency, float error_margin=2.0)
free helper function to calulate the timeouts required for the Read and Skip functions
Definition: readerHelpers.hpp:53
rtctk::telRepub::make_error_code
std::error_code make_error_code(MudpiProcessingError e)
Create std::error_code from ProcessingError.
Definition: mudpiProcessingError.hpp:113
logger.hpp
Logging Support Library based on log4cplus.