Пример #1
0
        /// <summary>
        ///     Flip a phase in the {@link WriterReaderPhaser} instance, {@link WriterReaderPhaser#flipPhase()}
        ///     can only be called while holding the readerLock().
        ///     {@link WriterReaderPhaser#flipPhase()} will return only after all writer critical sections (protected by
        ///     {@link WriterReaderPhaser#writerCriticalSectionEnter()} ()} and
        ///     {@link WriterReaderPhaser#writerCriticalSectionExit(long)} ()}) that may have been in flight when the
        ///     {@link WriterReaderPhaser#flipPhase()} call were made had completed.
        ///     No actual writer critical section activity is required for {@link WriterReaderPhaser#flipPhase()} to
        ///     succeed.
        ///     However, {@link WriterReaderPhaser#flipPhase()} is lock-free with respect to calls to
        ///     {@link WriterReaderPhaser#writerCriticalSectionEnter()} and
        ///     {@link WriterReaderPhaser#writerCriticalSectionExit(long)}. It may spin-wait for for active
        ///     writer critical section code to complete.
        /// </summary>
        /// <param name="yieldTimeNsec">The amount of time (in nanoseconds) to sleep in each yield if yield loop is needed.</param>
        public void FlipPhase(long yieldTimeNsec = 0)
        {
            if (!Monitor.IsEntered(readerLockObject))
            {
                throw new ThreadStateException("flipPhase() can only be called while holding the readerLock()");
            }

            var nextPhaseIsEven = (startEpoch.GetValue() < 0); // Current phase is odd...

            long initialStartValue;

            // First, clear currently unused [next] phase end epoch (to proper initial value for phase):
            if (nextPhaseIsEven)
            {
                initialStartValue = 0;
                evenEndEpoch.SetValue(initialStartValue);
            }
            else
            {
                initialStartValue = long.MinValue;
                oddEndEpoch.SetValue(initialStartValue);
            }

            // Next, reset start value, indicating new phase, and retain value at flip:
            var startValueAtFlip = startEpoch.GetAndSet(initialStartValue);

            // Now, spin until previous phase end value catches up with start value at flip:
            bool caughtUp;

            do
            {
                if (nextPhaseIsEven)
                {
                    caughtUp = (oddEndEpoch.GetValue() == startValueAtFlip);
                }
                else
                {
                    caughtUp = (evenEndEpoch.GetValue() == startValueAtFlip);
                }
                if (!caughtUp)
                {
                    if (yieldTimeNsec == 0)
                    {
                        //TODO: HdrHistogram
                        Task.Yield();
                    }
                    else
                    {
                        Thread.Sleep(TimeSpan.FromMilliseconds(yieldTimeNsec / 1000000.0));
                    }
                }
            } while (!caughtUp);
        }
Пример #2
0
 public void Can_get_and_set()
 {
     _num.SetValue(32);
     _num.GetAndSet(64).Should().Be(32);
     _num.GetValue().Should().Be(64);
 }