Skip to content

API proposal: Add SpinWait.SpinOnce overload to specify or disable the Sleep(1) threshold #26132

@kouvel

Description

@kouvel

SpinWait.SpinOnce has always used a fixed threshold before which it would start to call Thread.Sleep(1).

The jump in delay from spinning/Sleep(0) to a Sleep(1) is many orders in magnitude, and no single threshold will be good for every spinning usage scenario. An internal overload was added to allow specifying the Sleep(1) threshold in some places where we already encountered this issue:

In some cases, the scenario may also prefer to disable Sleep(1) altogether, for instance in Interlocked.CompareExchange() loops, see https://github.com/dotnet/corefx/issues/29595. Also, when a proper wait follows the spinning, the spin loop typically should not do Sleep(1) as doing the proper wait is usually better, for example:

Proposed API

    public struct SpinWait
    {
        public void SpinOnce(int minimumSleep1SpinCountThreshold) { }
    }

minimumSleep1SpinCountThreshold:

  • < -1: ArgumentOutOfRangeException
  • == -1: Sleep(1) will not be used
  • >= 0: Specifies a minimum spin count after which Sleep(1) may be used based on unspecified heuristics
    • For the implementation, we could probably make the value have a minimum of SpinWait.YieldThreshold such that the value returned by SpinWait.NextSpinWillYield would still be somewhat meaningful
  • Not sure about the name, suggestions?

Alternatives

Add a field for the Sleep(1) threshold to SpinWait and a constructor overload to set it.

  • Effects of increasing its size are unknown and could have undesired side-effects

@stephentoub

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions