I keep stumbling upon the following design pattern: operation X comprises two sequential operations A and B that must wait on some synchronization primitive. The timeout is specified for operation X.
In such scenario this is what I usually do:
Code: Select all
int32_t deadline = chTimeNow() + timeout;
...
timeout = deadline - chTimeNow(); // Operation A
if (timeout <= 0) return RDY_TIMEOUT;
chSemWaitTimeout
...
timeout = deadline - chTimeNow(); // Operation B
if (timeout <= 0) return RDY_TIMEOUT;
chSemWaitTimeout
...
Another place where I find this pattern is with condition variables. I want to specify the total timeout until the condition is met (for example, myvar >= 0), the CondVar may be signaled an indeterminate number of times by changes to myvar that do not meet myvar >= 0, so the loop will keep waiting for an indeterminate amount of time.
Code: Select all
int32_t deadline = chTimeNow() + timeout;
while (myvar < 0) {
timeout = deadline - chTimeNow();
if (timeout <= 0) break;
if (chCondWaitTimeout(&cond, timeout) == RDY_TIMEOUT) break;
}
Note that the time variables are int32_t instead of systime_t, because a signed var is needed in order to check for negative values of the timeout variable.
Almost every single time I've had to wait on a CondVar with a timeout, the requierement specifies the *total* timeout and thus the code above is required. Eventually I just wrote a chCondWaitDeadline wrapper around chCondWaitTimeout, and I wonder whether such a ser of alternative "Deadline" functions would be a worthy addition to the ChibiOS/RT API.