Commit 8b57944e authored by Joseph Noir's avatar Joseph Noir

Fix wait_for to work with RIOT vtimer

wait_until is not working, however (chrono is not available in RIOT).
parent 5f0fd702
...@@ -27,6 +27,11 @@ ...@@ -27,6 +27,11 @@
#include "mutex.hpp" #include "mutex.hpp"
extern "C" {
#include "sched.h"
#include "vtimer.h"
}
namespace caf { namespace caf {
enum class cv_status { no_timeout, timeout }; enum class cv_status { no_timeout, timeout };
...@@ -36,7 +41,6 @@ class condition_variable { ...@@ -36,7 +41,6 @@ class condition_variable {
public: public:
using native_handle_type = priority_queue_t*; using native_handle_type = priority_queue_t*;
// constexpr condition_variable() : m_queue{NULL} { }
inline condition_variable() { inline condition_variable() {
m_queue.first = NULL; m_queue.first = NULL;
} }
...@@ -68,10 +72,6 @@ class condition_variable { ...@@ -68,10 +72,6 @@ class condition_variable {
condition_variable(const condition_variable&); condition_variable(const condition_variable&);
condition_variable& operator=(const condition_variable&); condition_variable& operator=(const condition_variable&);
void do_timed_wait(unique_lock<mutex>& lock,
std::chrono::time_point<std::chrono::system_clock,
std::chrono::nanoseconds>) noexcept;
priority_queue_t m_queue; priority_queue_t m_queue;
}; };
...@@ -122,18 +122,22 @@ cv_status condition_variable::wait_for(unique_lock<mutex>& lock, ...@@ -122,18 +122,22 @@ cv_status condition_variable::wait_for(unique_lock<mutex>& lock,
if (timeout_duration <= timeout_duration.zero()) { if (timeout_duration <= timeout_duration.zero()) {
return cv_status::timeout; return cv_status::timeout;
} }
typedef time_point<system_clock, duration<long double, std::nano>> tpf; timex_t timeout, before, after;
typedef time_point<system_clock, nanoseconds> tpi; auto s = duration_cast<seconds>(timeout_duration);
tpf tpf_max = tpi::max(); timeout.seconds = s.count();
system_clock::time_point sys_now = system_clock::now(); timeout.microseconds = (duration_cast<microseconds>(timeout_duration) - s).count();
steady_clock::time_point sdy_now = steady_clock::now(); vtimer_now(&before);
if (tpf_max - timeout_duration > sys_now) { vtimer_t timer;
do_timed_wait(lock, sys_now + ceil<nanoseconds>(timeout_duration)); vtimer_set_wakeup(&timer, timeout, sched_active_pid);
wait(lock);
vtimer_now(&after);
vtimer_remove(&timer);
auto passed = timex_sub(after,before);
if (passed.seconds >= timeout.seconds && passed.microseconds >= timeout.microseconds) {
return cv_status::timeout;
} else { } else {
do_timed_wait(lock, tpi::max()); return cv_status::no_timeout;
} }
return steady_clock::now() - sdy_now < timeout_duration ?
cv_status::no_timeout : cv_status::timeout;
} }
template <class Rep, class Period, class Predicate> template <class Rep, class Period, class Predicate>
......
...@@ -85,40 +85,4 @@ void condition_variable::wait(unique_lock<mutex>& lock) noexcept { ...@@ -85,40 +85,4 @@ void condition_variable::wait(unique_lock<mutex>& lock) noexcept {
mutex_lock(lock.mutex()->native_handle()); mutex_lock(lock.mutex()->native_handle());
} }
void condition_variable::do_timed_wait(unique_lock<mutex>& lock,
time_point<system_clock,
nanoseconds> tp) noexcept {
if (!lock.owns_lock()) {
throw std::runtime_error("condition_variable::timed wait: mutex not locked");
}
nanoseconds d = tp.time_since_epoch();
if (d > nanoseconds(0x59682F000000E941)) {
d = nanoseconds(0x59682F000000E941);
}
timespec ts;
seconds s = duration_cast<seconds>(d);
typedef decltype(ts.tv_sec) ts_sec;
constexpr ts_sec ts_sec_max = std::numeric_limits<ts_sec>::max();
if (s.count() < ts_sec_max) {
ts.tv_sec = static_cast<ts_sec>(s.count());
ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((d - s).count());
} else {
ts.tv_sec = ts_sec_max;
ts.tv_nsec = std::giga::num - 1;
}
timex_t now, then, reltime;
// vtimer_now(&now) does not seem to work, so lets use chrono ...
system_clock::time_point sys_now = system_clock::now();
auto duration = sys_now.time_since_epoch();
now.seconds = duration_cast<seconds>(duration).count();
now.microseconds = (duration_cast<microseconds>(duration) - duration_cast<seconds>(duration)).count();
then.seconds = ts.tv_sec;
then.microseconds = ts.tv_nsec / 1000u;
reltime = timex_sub(then, now);
vtimer_t timer;
vtimer_set_wakeup(&timer, reltime, sched_active_pid);
wait(lock);
vtimer_remove(&timer);
}
} // namespace caf } // namespace caf
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment