/** * * \section COPYRIGHT * * Copyright 2013-2020 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the distribution. * */ /****************************************************************************** * File: timeout.h * Description: Millisecond resolution timeouts. Uses a dedicated thread to * call an optional callback function upon timeout expiry. * Reference: *****************************************************************************/ #ifndef SRSLTE_TIMEOUT_H #define SRSLTE_TIMEOUT_H #include "srslte/phy/utils/debug.h" #include #include #include #include namespace srslte { class timeout_callback { public: virtual void timeout_expired(uint32_t timeout_id) = 0; }; class timeout { public: timeout() : running(false), callback(NULL), thread(0), timeout_id(0) {} ~timeout() { if (running && callback) pthread_join(thread, NULL); } void start(int duration_msec_, uint32_t timeout_id_ = 0, timeout_callback* callback_ = NULL) { if (duration_msec_ < 0) return; reset(); gettimeofday(&start_time[1], NULL); duration_msec = duration_msec_; running = true; timeout_id = timeout_id_; callback = callback_; if (callback) pthread_create(&thread, NULL, &thread_start, this); } void reset() { if (callback) pthread_cancel(thread); running = false; } static void* thread_start(void* t_) { timeout* t = (timeout*)t_; t->thread_func(); return NULL; } void thread_func() { // substract time elapsed until now from timer duration gettimeofday(&start_time[2], NULL); get_time_interval(start_time); int32_t usec = duration_msec * 1000 - start_time[0].tv_usec; if (usec > 0) usleep(usec); if (callback && running) callback->timeout_expired(timeout_id); } bool expired() { if (running) { gettimeofday(&start_time[2], NULL); get_time_interval(start_time); return start_time[0].tv_usec > duration_msec * 1000; } else { return false; } } int32_t get_msec_to_expire() { if (running) { gettimeofday(&start_time[2], NULL); get_time_interval(start_time); return (duration_msec * 1000 - start_time[0].tv_usec) / 1000; } return 0; } bool is_running() { return running; } private: struct timeval start_time[3]; pthread_t thread; uint32_t timeout_id; timeout_callback* callback; bool running; int duration_msec; }; } // namespace srslte #endif // SRSLTE_TIMEOUT_H