A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/dotnet/runtime/issues/34812 below:

Add first class System.Threading.Lock type · Issue #34812 · dotnet/runtime · GitHub

Background and Motivation

Locking on any class has overhead from the dual role of the syncblock as both lock field and hashcode et al. (e.g. #34800)

Adding a first class lock type that didn't allow alternative uses and only acted as a lock would allow for a simpler and faster lock as well as be less ambiguous on type and purpose in source code.

API proposal

[Edit] by @kouvel based on #34812 (comment) and dotnet/csharplang#7104

namespace System.Threading
{
    // This is a lock that can be entered by one thread at a time. A thread may enter the lock recursively multiple
    // times, in which case the thread should also exit the lock the same number of times to fully exit the lock.
    public sealed class Lock
    {
        // Exceptions:
        //   - LockRecursionException if the lock was entered recursively by the current thread the maximum number of times
        public void Enter();

        // Returns true if the lock was acquired by the current thread, false otherwise.
        // Exceptions:
        //   - LockRecursionException if the lock was entered recursively by the current thread the maximum number of times.
        //     In this corner case an exception would be better than returning false, as the calling thread cannot make
        //     further progress with entering the lock before exiting it.
        public bool TryEnter();

        // Returns true if the lock was acquired by the current thread, false otherwise.
        // Exceptions:
        //   - ArgumentOutOfRangeException if the timeout value converted to an integer milliseconds value is negative
        //     and not equal to -1, or greater than Int32.MaxValue
        //   - LockRecursionException if the lock was entered recursively by the current thread the maximum number of times
        //     In this corner case an exception would be better than returning false, as the calling thread cannot make
        //     further progress with entering the lock before exiting it.
        public bool TryEnter(TimeSpan timeout);

        // Returns true if the lock was acquired, false otherwise.
        // Exceptions:
        //   - ArgumentOutOfRangeException if the timeout value is negative and not equal to -1
        //   - LockRecursionException if the lock was entered recursively by the current thread the maximum number of times
        //     In this corner case an exception would be better than returning false, as the calling thread cannot make
        //     further progress with entering the lock before exiting it.
        public bool TryEnter(int millisecondsTimeout);

        // Exceptions: SynchronizationLockException if the current thread does not own the lock
        public void Exit();

        // Returns true if the current thread holds the lock, false otherwise.
        //
        // This is analogous to Monitor.IsEntered(), but more similar to SpinLock.IsHeldByCurrentThread. There could
        // conceivably be a Lock.IsHeld as well similarly to SpinLock.IsHeld, or Lock.IsHeldByAnyThread to be more
        // precise, which would return true if the lock is held by any thread.
        public bool IsHeldByCurrentThread { get; }

        // Enters the lock and returns a holder. Enables integration with the "lock" keyword.
        // Exceptions:
        //   - LockRecursionException if the lock was entered recursively by the current thread the maximum number of times
        public Scope EnterScope();

        public ref struct Scope
        {
            // Exits the lock. No-op if Dispose was already called.
            // Exceptions: SynchronizationLockException if the current thread does not own the lock
            public void Dispose();
        }
    }
}
API Usage

Change in usage

private object _lock = new object();

Becomes the clearer

private Lock _lock = new Lock();

[Edit] by @kouvel

Usage example 1
_lock.Enter();
try
{
    // do something
}
finally
{
    _lock.Exit();
}
Usage example 2
using (_lock.EnterScope())
{
    // do something
}
Usage example 3

After the lock statement integration described in #34812 (comment), the following would use Lock.EnterScope and Scope.Dispose instead of using Monitor.

lock (_lock)
{
    // do something
}
TryEnterScope usage example

The following:

if (_lock.TryEnter())
{
    try
    {
        // do something
    }
    finally { _lock.Exit(); }
}

Could be slightly simplified to:

using (var tryScope = _lock.TryEnterScope())
{
    if (tryScope.WasEntered)
    {
        // do something
    }
}

The latter could also help to make the exit code path less expensive by avoiding a second thread-static lookup for the current thread ID.

Alternative Designs Risks

kevingosse, GrabYourPitchforks, halter73, nathan-moore, Speaqer and 49 morehexawyz, Sergio0694, Thealexbarney, Seb-stian, ksidirop-laerdal and 1 more


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4