Skip to content

Improved syntax for double-checked locking #130

@matwilko

Description

@matwilko

Problem

A fairly common occurrence when working with locks is to use double-checked locking to avoid acquiring the lock when it won't be necessary. However implementing this requires both a duplication of the condition and requiring statements inside the lock to be indented by three levels:

if (condition)
{
    lock(lockObj)
    {
        if (condition)
        {
            // statements
        }
    }
}

Even if we eliminate the brackets on the outer if and the lock and place them on the same line to reduce indentation, it gets to be a mess very quickly except with the shortest and most trivial of conditions:

if (condition) lock(lockObj) if (condition)
{
    // statements
}

Solution

In order to alleviate this, I'd propose combining the construct in a similar way to catch filters:

lock(lockObj) if (condition)
{
    // statements
}

However, this is already valid C#, so would impact backwards-compatibility. Instead, I'd suggest using when in place of if; It still reads off quite naturally, and is only a contextual keyword:

lock(lockObj) when (condition)
{
    // statements
}

As far as I can tell, this can't compile under C# 5/6, though I'm sure someone can find a counter-example ;)

I don't see developers 'abusing' the condition in the same way they might on catch (e.g. logging taking a lock) as they can already do this just before the lock is taken, but some might disagree!

I see the main problem being if a developer unsuspectingly uses a non-pure/side-effecting condition without realising it will be evaluated twice, but I'd hope good documentation would avoid this.

It's not the most pressing of concerns and doesn't really afford us any new expressiveness, but does follow nicely the current trend of reducing boilerplate by making certain parts of the language more concise, and appears to be a relatively simple lowering transformation.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions