Nicolas Holthaus
Nicolas Holthaus

Reputation: 8273

Does std::unique_lock::try_lock_until() busy wait?

I'm thinking of using the following code:

auto now = std::chrono::high_resolution_clock::now();

std::unique_lock<std::mutex> lock(mutex, std::defer_lock);
if(lock.try_lock_until(now + std::chrono::milliseconds(15))
{
    // swap some buffer pointers...
    lock.unlock();
}

However, it's not clear to me from the documentation if try_lock_until() is implemented as a busy wait or if the thread will yield/sleep in between tries (which is my desired behavior). Is this the best way to query a lock while minimizing thread resource usage?

Upvotes: 2

Views: 2426

Answers (1)

Thierry
Thierry

Reputation: 1139

The CppReference page for std::unique_lock::try_lock_until indeed only states it "Blocks until specified timeout_time has been reached or the lock is acquired". This is not just a shortcoming of the website though. The standard (I used the November 2014 working draft) carefully steers clear of specifying whether a thread has to yield while blocking on any kind of mutex, talking only about acquiring ownership.

For std::mutex, for instance, section 30.4.1.2.1 states

If one thread owns a mutex object, attempts by another thread to acquire ownership of that object will fail (for try_lock()) or block (for lock()) until the owning thread has released ownership with a call to unlock().

No mention of scheduling or yielding is made at all, though.

Furthermore, even if it did mention yield explicitly, that wouldn't help that much, as this_thread::yield (section 30.3.2) merely "Offers the implementation the opportunity to reschedule".

CppReference makes this more concrete, stating

The exact behavior of this function depends on the implementation, in particular on the mechanics of the OS scheduler in use and the state of the system. For example, a first-in-first-out realtime scheduler (SCHED_FIFO in Linux) would suspend the current thread and put it on the back of the queue of the same-priority threads that are ready to run (and if there are no other threads at the same priority, yield has no effect).

So I'm afraid the question of how try_lock_until is implemented in C++ cannot be answered. Perhaps you can ask a new question targeting a specific platform. For your second question ("Is this the best way to query a lock while minimizing thread resource usage?") the answer is yes, the best option your platform offers should be invoked using this API (though, as T.C. commented, try_lock_for seems like a better fit).

Upvotes: 3

Related Questions