Safely skip an task if mutex is locked

Viewed 587

Am struggling with bending my mind around mutexes/locks. The situation:

  • There is Task A that takes a relatively long time. It is executed irregularly in one thread (but only once at a time).
  • There is Task B which is quick and is very regularly called from another thread.
  • Both tasks work on the same memory and thus should not execute at the same time.
  • It is critical that Task B does not wait for Task A, because the context is communication with a GPU (texture transferring) after rendering and that would cause frame lag since Task A can take several frames.
  • Instead Task B should just be skipped if task A is currently running.
  • However Task A should never be skipped

What I have though so far: Thread for Task A (called irregularly):

{
  std::unique_lock<std::mutex> mlock(the_mutex);
  TaskA();
}

And Task B (which is hooked into the rendering thread)

{
  if mutex.try_lock()
  {
    TaskB();
    the_mutex.unlock();
  }
}

The_mutex is a common std::mutex for the object.

Is it really that easy for once, or am I missing something? After annoying bugs with multithreading in the past I've become insecure about this topic. Huge thanks in advance.

1 Answers

Your code is correct, but for exception safety and to protect from resource leaks you should better use RAII in task B. The general rule is "Use RAII lock guards (lock_guard, unique_lock, shared_lock), never call mutex.lock and mutex.unlock directly (RAII)".

std::unique_lock<std::mutex> mlock(the_mutex, std::defer_lock);
if (mlock.try_lock()) {
    TaskB();
}

or

std::unique_lock<std::mutex> mlock(the_mutex, std::try_to_lock);
if (mlock) {
    TaskB();
}
Related