Example #1
0
File: Msg.cs Project: xuzhe35/netmq
        public void Close()
        {
            if (!Check())
            {
                throw new FaultException();
            }

            if (m_type == MsgType.Pool)
            {
                // if not shared or reference counter drop to zero
                if ((m_flags & MsgFlags.Shared) == 0 || m_atomicCounter.Decrement() == 0)
                {
                    BufferPool.Return(m_data);
                }

                m_atomicCounter.Dispose();
                m_atomicCounter = null;
            }

            m_data = null;

            //  Make the message invalid.
            m_type = MsgType.Invalid;
        }
Example #2
0
        public void CouldDispose()
        {
            var counter = 0;

            Assert.IsFalse(AtomicCounter.GetIsDisposed(ref counter));
            Assert.AreEqual(1, AtomicCounter.Increment(ref counter));
            Assert.AreEqual(2, AtomicCounter.Increment(ref counter));

            Assert.Throws <InvalidOperationException>(() => { AtomicCounter.Dispose(ref counter); });

            Assert.AreEqual(1, AtomicCounter.Decrement(ref counter));
            Assert.AreEqual(0, AtomicCounter.DecrementIfOne(ref counter));

            Assert.IsFalse(AtomicCounter.GetIsDisposed(ref counter));

            AtomicCounter.Dispose(ref counter);

            Assert.IsTrue(AtomicCounter.GetIsDisposed(ref counter));
        }
Example #3
0
 private DataBlock()
 {
     AtomicCounter.Dispose(ref _refCount);
 }
Example #4
0
            public void Dispose(bool disposing)
            {
                if (!_isSharedMemory)
                {
                    DoDispose();
                }
                else
                {
                    lock (this)
                    {
                        DoDispose();
                    }
                }

                void DoDispose()
                {
                    if (!disposing)
                    {
                        // Cache has a weak reference, so finalizer could start running while a handle is still in the cache
                        // As if _rc was 1 and we called DecrementIfOne - if successful, no resurrect is possible
                        // because Retain uses IncrementIfRetained.

                        var current  = Volatile.Read(ref _rc);
                        var existing = Interlocked.CompareExchange(ref _rc, 0, current);
                        if (existing != current)
                        {
                            // Resurrected while we tried to set rc to zero.
                            // What if rc was wrong and not 1? At some point all new users will
                            // dispose the proxy and it will be in the cache with
                            // positive rc but without GC root, then it will be
                            // collected and finalized and will return to this
                            // place where we will try to set rc to 0 again.
                            // TODO trace this condition, it indicates dropped proxies
                            // From user code it could be possible only when manually using cursors
                            // and forgetting to dispose them, so all blame is on users, but we should not fail.

                            ThrowHelper.AssertFailFast(existing > 1, "existing > 1 when resurrected");
                            return;
                        }
                    }
                    else
                    {
                        var remaining = AtomicCounter.Decrement(ref _rc);
                        if (remaining > 1)
                        {
                            return;
                        }

                        if (AtomicCounter.DecrementIfOne(ref _rc) != 0)
                        {
                            return;
                        }
                    }

                    ThrowHelper.AssertFailFast(_rc == 0, "_rc must be 0 to proceed with proxy disposal");

                    try
                    {
                        // remove self from cache
                        _cache._blocks.TryRemove(_key, out var handle);
                        if (handle.IsAllocated)
                        {
                            handle.Free();
                        }
                    }
                    finally
                    {
                        // If we are shutting down, e.g. unhandled exception in other threads
                        // increase the chances we do release shared memory ref.

#pragma warning disable 618
                        // ReSharper disable once InconsistentlySynchronizedField
                        Block.DisposeFree();
#pragma warning restore 618
                    }

                    // Do not pool finalized objects.
                    // TODO (review) proxy does not have ref type fields,
                    // probably could add to pool without thinking about GC/finalization order.
                    // However, this case should be very rare (e.g. unhandled exception)
                    // and we care about releasing RC of shared memory above all.
                    if (disposing)
                    {
                        GC.SuppressFinalize(this);
                        // ReSharper disable once InconsistentlySynchronizedField
                        Block = default;
                        _key  = default;
                        AtomicCounter.Dispose(ref _rc);
                        _isSharedMemory = default;
                    }
                }
            }