File: FrameworkFork\System.ServiceModel\System\ServiceModel\Channels\BufferedMessageData.cs
Web Access
Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Runtime;
using Microsoft.Xml;
 
namespace System.ServiceModel.Channels
{
    internal abstract class BufferedMessageData : IBufferedMessageData
    {
        private ArraySegment<byte> _buffer;
        private BufferManager _bufferManager;
        private int _refCount;
        private int _outstandingReaders;
        private bool _multipleUsers;
        private RecycledMessageState _messageState;
        private SynchronizedPool<RecycledMessageState> _messageStatePool;
 
        public BufferedMessageData(SynchronizedPool<RecycledMessageState> messageStatePool)
        {
            _messageStatePool = messageStatePool;
        }
 
        public ArraySegment<byte> Buffer
        {
            get { return _buffer; }
        }
 
        public BufferManager BufferManager
        {
            get { return _bufferManager; }
        }
 
        public virtual XmlDictionaryReaderQuotas Quotas
        {
            get { return XmlDictionaryReaderQuotas.Max; }
        }
 
        public abstract MessageEncoder MessageEncoder { get; }
 
        private object ThisLock
        {
            get { return this; }
        }
 
        public void EnableMultipleUsers()
        {
            _multipleUsers = true;
        }
 
        public void Close()
        {
            if (_multipleUsers)
            {
                lock (ThisLock)
                {
                    if (--_refCount == 0)
                    {
                        DoClose();
                    }
                }
            }
            else
            {
                DoClose();
            }
        }
 
        private void DoClose()
        {
            _bufferManager.ReturnBuffer(_buffer.Array);
            if (_outstandingReaders == 0)
            {
                _bufferManager = null;
                _buffer = new ArraySegment<byte>();
                OnClosed();
            }
        }
 
        public void DoReturnMessageState(RecycledMessageState messageState)
        {
            if (_messageState == null)
            {
                _messageState = messageState;
            }
            else
            {
                _messageStatePool.Return(messageState);
            }
        }
 
        private void DoReturnXmlReader(XmlDictionaryReader reader)
        {
            ReturnXmlReader(reader);
            _outstandingReaders--;
        }
 
        public RecycledMessageState DoTakeMessageState()
        {
            RecycledMessageState messageState = _messageState;
            if (messageState != null)
            {
                _messageState = null;
                return messageState;
            }
            else
            {
                return _messageStatePool.Take();
            }
        }
 
        private XmlDictionaryReader DoTakeXmlReader()
        {
            XmlDictionaryReader reader = TakeXmlReader();
            _outstandingReaders++;
            return reader;
        }
 
        public XmlDictionaryReader GetMessageReader()
        {
            if (_multipleUsers)
            {
                lock (ThisLock)
                {
                    return DoTakeXmlReader();
                }
            }
            else
            {
                return DoTakeXmlReader();
            }
        }
 
        public void OnXmlReaderClosed(XmlDictionaryReader reader)
        {
            if (_multipleUsers)
            {
                lock (ThisLock)
                {
                    DoReturnXmlReader(reader);
                }
            }
            else
            {
                DoReturnXmlReader(reader);
            }
        }
 
        protected virtual void OnClosed()
        {
        }
 
        public RecycledMessageState TakeMessageState()
        {
            if (_multipleUsers)
            {
                lock (ThisLock)
                {
                    return DoTakeMessageState();
                }
            }
            else
            {
                return DoTakeMessageState();
            }
        }
 
        protected abstract XmlDictionaryReader TakeXmlReader();
 
        public void Open()
        {
            lock (ThisLock)
            {
                _refCount++;
            }
        }
 
        public void Open(ArraySegment<byte> buffer, BufferManager bufferManager)
        {
            _refCount = 1;
            _bufferManager = bufferManager;
            _buffer = buffer;
            _multipleUsers = false;
        }
 
        protected abstract void ReturnXmlReader(XmlDictionaryReader xmlReader);
 
        public void ReturnMessageState(RecycledMessageState messageState)
        {
            if (_multipleUsers)
            {
                lock (ThisLock)
                {
                    DoReturnMessageState(messageState);
                }
            }
            else
            {
                DoReturnMessageState(messageState);
            }
        }
    }
}