Пример #1
0
            private LockCookie EnterSlow()
            {
                // Attempt to steal the ownership. Take a regular lock to ensure that only one thread is trying to steal it at a time.
                lock (this)
                {
                    // We are the new fast thread now!
                    var oldEntry = _current;
                    _current = new LockCookie(Environment.CurrentManagedThreadId);

                    // After MemoryBarrierProcessWide, we can be sure that the Volatile.Read done by the fast thread will see that it is not a fast
                    // thread anymore, and thus it will not attempt to enter the lock.
                    Interlocked.MemoryBarrierProcessWide();

                    // Keep looping as long as the lock is taken by other thread
                    SpinWait sw = new SpinWait();
                    while (oldEntry.Taken)
                    {
                        sw.SpinOnce();
                    }

                    // We have seen that the other thread released the lock by setting Taken to false.
                    // However, on platforms with weak memory ordering (ex: ARM32, ARM64) observing that does not guarantee that the writes executed by that
                    // thread prior to releasing the lock are all committed to the shared memory.
                    // We could fix that by doing the release via Volatile.Write, but we do not want to add expense to every release on the fast path.
                    // Instead we will do another MemoryBarrierProcessWide here.

                    // NOTE: not needed on x86/x64
                    Interlocked.MemoryBarrierProcessWide();

                    _current.Taken = true;
                    return(_current);
                }
            }
Пример #2
0
            private LockCookie EnterSlow()
            {
                // Attempt to steal the ownership. Take a regular lock to ensure that only one thread is trying to steal it at a time.
                lock (this)
                {
                    // We are the new fast thread now!
                    var oldEntry = _current;
                    _current = new LockCookie(Environment.CurrentManagedThreadId);

                    // MemoryBarrierProcessWide ensures, process-wide, that our write to _current becomes visible
                    // to every thread, and all writes by other threads become visible to us before we can continue.
                    // As a result any other thread that sets Taken to true either:
                    //    a) made it past the read of _current and owns the lock OR
                    //    b) will see that _current has changed and will revert Taken without taking the lock
                    // Thus we only need to wait for 'Taken' to become false and claim the lock for ourselves.
                    // 'Taken' may yet switch to true after that, but that cannot result in other thread owning the lock.
                    Interlocked.MemoryBarrierProcessWide();

                    // Keep looping as long as the lock is taken by other thread
                    SpinWait sw = new SpinWait();
                    while (oldEntry.Taken)
                    {
                        sw.SpinOnce();
                    }

                    _current.Taken = true;
                    return(_current);
                }
            }
 public async Task HandleDisconnectedAsync(MqttClientDisconnectedEventArgs eventArgs)
 {
     _connected = false;
     Interlocked.MemoryBarrierProcessWide();
     if (!(_client is null) && eventArgs.ReasonCode != MqttClientDisconnectReason.AdministrativeAction && !_connected)
     {
         _logger.LogWarning(eventArgs.Exception, "MQTT client has disconnected, reason: {0}, trying to reconnect.", eventArgs.ReasonCode);
         await DoConnectAsync(_client, CancellationToken.None);
     }
 }
 static void Test1()
 {
     x = 1;
     // CPU has the ability to reorder the code instructions, if the codes have no dependencies
     // like there Test1 and Test has no dependencies, so CPU can run Test1 and Test2 in any order
     // use MemoryBarrierProcessWide to block any CPU
     // or use Interlocked.MemoryBarrier() in both Test 1 and Test2
     Interlocked.MemoryBarrierProcessWide();
     a = y;
 }
        void Update(ILogger newRoot, ILogger newCached, bool frozen)
        {
            _root   = newRoot;
            _cached = newCached;
            _frozen = frozen;

            // https://github.com/dotnet/runtime/issues/20500#issuecomment-284774431
            // Publish `_cached` and `_frozen`. This is useful here because it means that once the logger is frozen - which
            // we always expect - reads don't require any synchronization/interlocked instructions.
            Interlocked.MemoryBarrierProcessWide();
        }
Пример #6
0
        public Logger Freeze()
        {
            lock (_sync)
            {
                if (_frozen)
                {
                    throw new InvalidOperationException("The logger is already frozen.");
                }

                _frozen = true;

                // https://github.com/dotnet/runtime/issues/20500#issuecomment-284774431
                // Publish `_logger` and `_frozen`. This is useful here because it means that once the logger is frozen - which
                // we always expect - reads don't require any synchronization/interlocked instructions.
                Interlocked.MemoryBarrierProcessWide();

                return(_logger);
            }
        }
Пример #7
0
        private static void InterlockedOperations()
        {
            //_counter becomes 1
            Interlocked.Increment(ref _counter);
            // _counter becomes 0
            Interlocked.Decrement(ref _counter);
            // Add: _counter becomes 2
            Interlocked.Add(ref _counter, 2);
            //Subtract: _counter becomes 0
            Interlocked.Add(ref _counter, -2);
            // Reads 64 bit field
            Console.WriteLine(Interlocked.Read(ref _counter));
            // Swaps _counter value with 10
            Console.WriteLine(Interlocked.Exchange(ref _counter, 10));
            //Checks if _counter is 10 and if yes replace with 100
            Console.WriteLine(Interlocked.CompareExchange(ref _counter, 100, 10)); // _counter becomes 100

            Interlocked.MemoryBarrier();

            Interlocked.MemoryBarrierProcessWide();
        }
Пример #8
0
            private LockCookie EnterSlow()
            {
                // Attempt to steal the ownership. Take a regular lock to ensure that only one thread is trying to steal it at a time.
                lock (this)
                {
                    // We are the new fast thread now!
                    var oldEntry = _current;
                    _current = new LockCookie(Environment.CurrentManagedThreadId);

                    // After MemoryBarrierProcessWide, we can be sure that the Volatile.Read done by the fast thread will see that it is not a fast
                    // thread anymore, and thus it will not attempt to enter the lock.
                    Interlocked.MemoryBarrierProcessWide();

                    // Keep looping as long as the lock is taken by other thread
                    SpinWait sw = new SpinWait();
                    while (oldEntry.Taken)
                    {
                        sw.SpinOnce();
                    }

                    _current.Taken = true;
                    return(_current);
                }
            }
 static void Test1()
 {
     x = 1;
     Interlocked.MemoryBarrierProcessWide();
     a = y;
 }
 private static void BarrierUsingInterlockedProcessWideBarrier()
 {
     b = c;
     Interlocked.MemoryBarrierProcessWide();
     a = 1;
 }