From e7e22b4038cf96796bae27411479a2ce8eae3db7 Mon Sep 17 00:00:00 2001 From: Giuseppe Date: Fri, 12 Feb 2021 11:55:20 +0100 Subject: [PATCH] NetworkClock: close the gap between the waiter and the time if a time reset is detected Co-authored-by: Daniele E. Domenichelli --- doc/release/yarp_3_4/detect_clock_reset.md | 8 ++++++++ src/libYARP_os/src/yarp/os/NetworkClock.cpp | 10 +++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 doc/release/yarp_3_4/detect_clock_reset.md diff --git a/doc/release/yarp_3_4/detect_clock_reset.md b/doc/release/yarp_3_4/detect_clock_reset.md new file mode 100644 index 00000000000..1bc142fb650 --- /dev/null +++ b/doc/release/yarp_3_4/detect_clock_reset.md @@ -0,0 +1,8 @@ +detect_clock_reset {#yarp_3_4} +----------------------- + +### Libraries + +#### `os` + +* If in a `yarp::os::NetworkClock` a clock reset is detected, fill the gap between the waiter and the time published by the network clock port. A network clock reset is defined as a jump in the past of the time published by the network clock port. This fix avoids that all the threads that are waiting a `yarp::os::NetworkClock::delay` call on that network clock remain blocked when a time reset occurs. diff --git a/src/libYARP_os/src/yarp/os/NetworkClock.cpp b/src/libYARP_os/src/yarp/os/NetworkClock.cpp index 68c8a7f4dea..59bc980a4c5 100644 --- a/src/libYARP_os/src/yarp/os/NetworkClock.cpp +++ b/src/libYARP_os/src/yarp/os/NetworkClock.cpp @@ -103,6 +103,7 @@ bool NetworkClock::Private::read(ConnectionReader& reader) } timeMutex.lock(); + double oldTime = _time; sec = bot.get(0).asInt32(); nsec = bot.get(1).asInt32(); _time = sec + (nsec * 1e-9); @@ -111,7 +112,14 @@ bool NetworkClock::Private::read(ConnectionReader& reader) listMutex.lock(); auto waiter_it = waiters->begin(); - while (waiter_it != waiters->end()) { + if (oldTime > _time) { + // Update the wake-up time. In case of a time reset it closes the gap + // between the waiter and _time. + waiter_it->first = _time + (waiter_it->first - oldTime); + } + + while (waiter_it != waiters->end()) + { if (waiter_it->first - _time < 1E-12) { Semaphore* waiterSemaphore = waiter_it->second; waiter_it = waiters->erase(waiter_it);