Joe
Joe

Reputation: 6806

What is the use-case for TryEnterCriticalSection?

I've been using Windows CRITICAL_SECTION since the 1990s and I've been aware of the TryEnterCriticalSection function since it first appeared. I understand that it's supposed to help me avoid a context switch and all that.

But it just occurred to me that I have never used it. Not once. Nor have I ever felt I needed to use it. In fact, I can't think of a situation in which I would.

Generally when I need to get an exclusive lock on something, I need that lock and I need it now. I can't put it off until later. I certainly can't just say, "oh well, I won't update that data after all". So I need EnterCriticalSection, not TryEnterCriticalSection

So what exactly is the use case for TryEnterCriticalSection?

I've Googled this, of course. I've found plenty of quick descriptions on how to use it but almost no real-world examples of why. I did find this example from Intel that, frankly doesn't help much:

CRITICAL_SECTION cs;

    void threadfoo()
    {
        while(TryEnterCriticalSection(&cs) == FALSE)
        {
             // some useful work
        }

        // Critical Section of Code

        LeaveCriticalSection (&cs);
    }

    // other work
}

What exactly is a scenario in which I can do "some useful work" while I'm waiting for my lock? I'd love to avoid thread-contention but in my code, by the time I need the critical section, I've already been forced to do all that "useful work" in order to get the values that I'm updating in shared data (for which I need the critical section in the first place).

Does anyone have a real-world example?

Upvotes: 1

Views: 603

Answers (3)

Alex Guteniev
Alex Guteniev

Reputation: 13689

In C++11 therestd::lock which employs deadlock-avoidance algorithm.

In C++17 this has been elaborated to std::scoped_lock class.

This algorithm tries to lock on mutexes in one order, and then in another, until succeeds. It takes try_lock to implement this approach.

Having try_lock method in C++ is called Lockable named requirement, whereas mutexes with only lock and unlock are BasicLockable.

So if you build C++ mutex on top of CTRITICAL_SECTION, and you want to implement Lockable, or you'll want to implement lock avoidance directly on CRITICAL_SECTION, you'll need TryEnterCriticalSection


Additionally you can implement timed mutex on TryEnterCriticalSection. You can do few iterations of TryEnterCriticalSection, then call Sleep with increasing delay time, until TryEnterCriticalSection succeeds or deadline has expired. It is not a very good idea though. Really timed mutexes based on user-space WIndows synchronization objects are implemented on SleepConditionVariableSRW, SleepConditionVariableCS or WaitOnAddress.

Upvotes: 1

SoronelHaetir
SoronelHaetir

Reputation: 15162

Because windows CS are recursive TryEnterCriticalSection allows a thread to check whether it already owns a CS without risk of stalling.

Another case would be if you have a thread that occasionally needs to perform some locked work but usually does something else, you could use TryEnterCriticalSection and only perform the locked work if you actually got the lock.

Upvotes: 0

As an example you might have multiple threads that each produce a high volume of messages (events of some sort) that all need to go on a shared queue.

Since there's going to be frequent contention on the lock on the shared queue, each thread can have a local queue and then, whenever the TryEnterCriticalSection call succeeds for the current thread, it copies everything it has in its local queue to the shared one and releases the CS again.

Upvotes: 2

Related Questions