Is there a standard function to busy wait for a condition or until a timeout

2k Views Asked by At

I need to wait in my program for a subsystem. In different places a have to wait for different conditions. I know I could also make use of threads and conditions variables. But since the subsystem (bare metal programmed in C) is connected via shared memory with no interrupts registered to it -- one thread needs to poll anyways.

So I did the following template to be able to wait for anything. I was wondering whether there is already a STL function which could be used for that?

#include <chrono>
#include <thread>


//given poll interval
template<typename predicate, 
         typename Rep1, typename Period1, 
         typename Rep2, typename Period2> 
bool waitActiveFor(predicate check,
                   std::chrono::duration<Rep1, Period1> x_timeout,
                   std::chrono::duration<Rep2, Period2> x_pollInterval)
{
  auto x_start = std::chrono::steady_clock::now();
  while (true)
  {
    if (check())
      return true;

    if ((std::chrono::steady_clock::now() - x_start) > x_timeout)
      return false;

    std::this_thread::sleep_for(x_pollInterval);
  }
}

//no poll interval defined
template<typename predicate, 
         typename Rep, typename Period>
bool waitActiveFor(predicate check,
                   std::chrono::duration<Rep, Period> x_timeout)
{
  auto x_start = std::chrono::steady_clock::now();
  while (true)
  {
    if (check())
      return true;

    if ((std::chrono::steady_clock::now() - x_start) > x_timeout)
      return false;

    std::this_thread::yield();
  }
}

running sample


2019-05-23: Code update regarding the comments and answers

2

There are 2 best solutions below

2
On BEST ANSWER

Not to my knowledge. In general, the goal is to wait without burning clock cycles, so the standard library is geared toward that usage.

I'm aware of std::this_thread::yield() which is what I usually use when I want to busy wait, but since you've got a poll interval, sleep_for() is probably your best bet.

2
On

Is there a standard function to busy wait for a condition or until a timeout

No. There are functions for blocking until timeout or notification, but not for busy waiting. However, that is indeed fairly simple to write, as you've demonstrated.

An important consideration regarding the context: There is no guarantee in general that the check() is still true after the function has returned true. To achieve that guarantee, you must make sure that anything that touches the shared memory (including the subsystem) won't change the check to be false, with the exception of the thread that does the polling (and that means there can only be one thread doing so).


Bonus code review

  • Since you have a template anyway, it is probably a good idea to let the type of the time arguments be templated as well, so that the user can use any std::chrono::time_point and thereby any unit the wish. In addition, you can get rid of duration_casts and count in your template.