19 #include "artdaq/TransferPlugins/detail/Timeout.hh"
20 #include "artdaq/DAQdata/Globals.hh"
25 Timeout::timeoutspec::timeoutspec()
26 : desc(), tag(), function()
28 , missed_periods(), check()
29 { TRACE( 18,
"Timeout::timeoutspec ctor this=%p",
this );
31 Timeout::timeoutspec::timeoutspec(
const timeoutspec & other )
32 : desc(other.desc), tag(other.tag), function(other.function)
33 , ts(other.ts), period(other.period)
34 , missed_periods(other.missed_periods), check(other.check)
35 { TRACE( 18,
"Timeout::timeoutspec copy ctor" );
38 { TRACE( 18,
"Timeout::timeoutspec copy assignment (operator=) other.desc="+other.
desc );
54 TRACE( 16,
"Timeout ctor" );
93 TRACE( 19,
"add_periodic - desc="+std::string(desc)+
" period_us=%lu start_us=%lu"
94 , period_us, start_us );
124 tmo.
desc = desc.c_str();
135 , uint64_t* tmo_tod_us)
139 TRACE( 15,
"get_next_expired_timeout b4 get_clear_next_expired_timeout" );
143 TRACE( 18,
"get_next_expired_timeout - get_clear_next_expired_timeout returned false" );
144 desc = std::string(
"");
159 std::unique_lock<std::mutex> ulock(lock_mutex_);
160 size_t active_time_size = active_time_.size();
161 if (active_time_size == 0)
163 TRACE( 17,
"get_next_timeout_delay active_.size() == 0" );
168 TRACE( 17,
"get_next_timeout_delay active_.size() != 0 %lu",active_time_size );
170 timeoutspec* tmo = &tmospecs_[(*(active_time_.begin())).second];
189 tmo = delay_us / 1000;
198 std::map<uint64_t, size_t>::iterator itactive;
199 std::list<size_t>::iterator itfree;
200 for (
unsigned ii = 0; ii < tmospecs_.size(); ++ii)
201 tmospecs_[ii].check = 1;
202 for (itactive = active_time_.begin(); itactive != active_time_.end(); ++itactive)
203 tmospecs_[(*itactive).second].check--;
204 for (itfree = free_.begin(); itfree != free_.end(); ++itfree)
205 tmospecs_[*itfree].check--;
206 for (
unsigned ii = 0; ii < tmospecs_.size(); ++ii)
207 if (tmospecs_[ii].check != 0)
return false;
214 gettimeofday(&tv, NULL);
215 return (uint64_t)tv.tv_sec * 1000000 + tv.tv_usec;
220 Timeout::timeoutlist_init()
222 size_t list_sz = tmospecs_.size();
223 for (
size_t ii = 0; ii < list_sz; ++ii)
225 free_.push_front(ii);
230 int Timeout::get_clear_next_expired_timeout(timeoutspec& tmo
231 , uint64_t tod_now_us)
234 if (active_time_.size() == 0)
236 TRACE( 17,
"get_clear_next_expired_timeout - nothing to get/clear!" );
241 std::unique_lock<std::mutex> ulock(lock_mutex_);
242 std::multimap<uint64_t, size_t>::iterator itfront = active_time_.begin();
243 size_t idx = (*itfront).second;
244 if (tmospecs_[idx].tmo_tod_us < tod_now_us)
246 tmo = tmospecs_[idx];
247 TRACE( 17,
"get_clear_next_expired_timeout - clearing tag=%p desc="+tmo.desc+
" period=%lu idx=%lu"
248 , tmo.tag, tmo.period_us, idx );
250 active_time_.erase(itfront);
257 uint64_t period_us = tmo.period_us;
258 delta_us = tod_now_us - tmo.tmo_tod_us;
259 skipped = delta_us / period_us;
260 assert( skipped >= 0 );
261 tmo.missed_periods += skipped;
264 period_us += period_us * skipped;
265 tmospecs_[idx].tmo_tod_us += period_us;
266 active_time_.insert(std::pair<uint64_t, size_t>(tmospecs_[idx].tmo_tod_us, idx));
268 ,
"get_clear_next_expired_timeout - periodic timeout desc="+tmo.desc
269 +
" period_us=%lu delta_us=%lu skipped=%d next tmo at:%lu"
270 , period_us, delta_us, skipped, tmospecs_[idx].tmo_tod_us );
275 std::unordered_multimap<std::string, size_t>::iterator i2;
276 i2 = active_desc_.equal_range(tmospecs_[idx].desc).first;
279 if (i2->second == idx)
283 active_desc_.erase(i2);
284 free_.push_front(idx);
289 TRACE( 17,
"get_clear_next_expired_timeout - front %lu NOT before ts_now %lu - not clearing!"
290 , tmospecs_[idx].tmo_tod_us, tod_now_us );
300 TRACE( 18,
"copy_in_timeout desc="+std::string(desc) );
315 assert( free_.size() );
318 std::unique_lock<std::mutex> ulock(lock_mutex_);
319 size_t idx = free_.front();
321 tmospecs_[idx] = tmo;
322 TRACE( 20,
"copy_in_timeout timeoutspec desc="+tmo.desc );
323 active_time_.insert(std::pair<uint64_t, size_t>(tmo.tmo_tod_us, idx));
324 active_desc_.insert(std::pair<std::string, size_t>(tmo.desc, idx));
332 std::unordered_multimap<std::string, size_t>::iterator ii, ee;
333 std::unique_lock<std::mutex> ulock(lock_mutex_);
334 auto pairOfIters = active_desc_.equal_range(desc);
335 ii = pairOfIters.first;
336 ee = pairOfIters.second;
337 for (; ii != ee && ii->first.compare(desc) == 0; ++ii)
339 size_t idx = ii->second;
340 if (tmospecs_[idx].tag == tag)
344 uint64_t tmo_tod_us = tmospecs_[idx].tmo_tod_us;
347 std::multimap<uint64_t, size_t>::iterator i2;
348 i2 = active_time_.equal_range(tmo_tod_us).first;
351 if (i2->second == idx)
356 active_desc_.erase(ii);
357 active_time_.erase(i2);
358 free_.push_front(idx);
362 TRACE( 22,
"cancel_timeout returning %d", retsts );
369 std::map<uint64_t, size_t>::iterator ii = active_time_.begin(), ee = active_time_.end();
370 for (; ii != ee; ++ii)
372 TRACE( 3,
"list_active_time %lu desc="+tmospecs_[(*ii).second].desc, (*ii).first );
void copy_in_timeout(const char *desc, uint64_t period_us, uint64_t start_us=0)
Add a timeout with the given parameters.
void add_relative(const char *desc, void *tag, std::function< void()> &function, int rel_ms)
Add a periodic timeout to the Timeout container.
void * tag
could be file descriptor (fd)
std::function< void()> function
Function to execute at Timeout.
uint64_t tmo_tod_us
When the function should be executed (gettimeofday, microseconds)
int get_next_timeout_msdly()
Get the amount to wait for the next timeout to occur.
int check
Check the timeoutspec.
int missed_periods
Number of periods that passed while the function was executing.
void get_next_timeout_delay(int64_t *delay_us)
Get the amount to wait for the next timeout to occur.
uint64_t period_us
0 if not periodic
Specification for a Timeout function.
int get_next_expired_timeout(std::string &desc, void **tag, std::function< void()> &function, uint64_t *tmo_tod_us)
Get a timeout that has expired.
uint64_t gettimeofday_us()
Get the current time of day in microseconds (from gettimeofday system call)
bool is_consistent()
Run a consistency check on all confiugured timeouts.
std::string desc
Description of the Timeout function.
bool cancel_timeout(void *tag, std::string desc)
Cancel the timeout having the given description and tag.
void add_periodic(const char *desc, void *tag, std::function< void()> &function, uint64_t period_us, uint64_t start_us=0)
Add a periodic timeout to the Timeout container.
Timeout(int max_tmos=100)
Construct a Timeout object.
void list_active_time()
TRACE all active timeouts.