BufferCache.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / MS / Internal / FontCache / BufferCache.cs / 1305600 / BufferCache.cs

                            // -------------------------------------------------------------------------- 
//
// File: BufferCache.cs
//
// Copyright (C) Microsoft Corporation.  All rights reserved. 
//
// Description: BufferCache class implementation. 
// 
//---------------------------------------------------------------------------
 
using System;
using System.Threading;
using MS.Internal.Text.TextInterface;
 
namespace MS.Internal.FontCache
{ 
    ///  
    /// A static, thread safe array cache used to minimize heap allocations.
    ///  
    /// 
    /// Cached arrays are not zero initialized, and they may be larger than
    /// the requested number of elements.
    ///  
    internal static class BufferCache
    { 
        //----------------------------------------------------- 
        //
        //  Internal Methods 
        //
        //-----------------------------------------------------

        #region Internal Methods 

        ///  
        /// Attempts to release all allocated memory.  Has no effect if the cache 
        /// is locked by another thread.
        ///  
        internal static void Reset()
        {
            if (Interlocked.Increment(ref _mutex) == 1)
            { 
                _buffers = null;
            } 
            Interlocked.Decrement(ref _mutex); 
        }
 
        /// 
        /// Returns a GlyphMetrics[].
        /// 
        ///  
        /// Minimum number of elements in the array.
        ///  
        internal static GlyphMetrics[] GetGlyphMetrics(int length) 
        {
            GlyphMetrics[] glyphMetrics = (GlyphMetrics[])GetBuffer(length, GlyphMetricsIndex); 

            if (glyphMetrics == null)
            {
                glyphMetrics = new GlyphMetrics[length]; 
            }
 
            return glyphMetrics; 
        }
 
        /// 
        /// Releases a previously allocated GlyphMetrics[], possibly adding it
        /// to the cache.
        ///  
        /// 
        /// It is not strictly necessary to call this method after receiving an 
        /// array.  The penalty is the performance hit of doing a heap allocation 
        /// on the next request if this method is not called.
        ///  
        internal static void ReleaseGlyphMetrics(GlyphMetrics[] glyphMetrics)
        {
            ReleaseBuffer(glyphMetrics, GlyphMetricsIndex);
        } 

        ///  
        /// Returns a ushort[]. 
        /// 
        ///  
        /// Minimum number of elements in the array.
        /// 
        internal static ushort[] GetUShorts(int length)
        { 
            ushort[] ushorts = (ushort[])GetBuffer(length, UShortsIndex);
 
            if (ushorts == null) 
            {
                ushorts = new ushort[length]; 
            }

            return ushorts;
        } 

        ///  
        /// Releases a previously allocated ushort[], possibly adding it 
        /// to the cache.
        ///  
        /// 
        /// It is not strictly necessary to call this method after receiving an
        /// array.  The penalty is the performance hit of doing a heap allocation
        /// on the next request if this method is not called. 
        /// 
        internal static void ReleaseUShorts(ushort[] ushorts) 
        { 
            ReleaseBuffer(ushorts, UShortsIndex);
        } 

        /// 
        /// Returns a uint[].
        ///  
        /// 
        /// Minimum number of elements in the array. 
        ///  
        internal static uint[] GetUInts(int length)
        { 
            uint[] uints = (uint[])GetBuffer(length, UIntsIndex);

            if (uints == null)
            { 
                uints = new uint[length];
            } 
 
            return uints;
        } 

        /// 
        /// Releases a previously allocated uint[], possibly adding it
        /// to the cache. 
        /// 
        ///  
        /// It is not strictly necessary to call this method after receiving an 
        /// array.  The penalty is the performance hit of doing a heap allocation
        /// on the next request if this method is not called. 
        /// 
        internal static void ReleaseUInts(uint[] uints)
        {
            ReleaseBuffer(uints, UIntsIndex); 
        }
 
        #endregion Internal Methods 

        //------------------------------------------------------ 
        //
        //  Private Methods
        //
        //----------------------------------------------------- 

        #region Private Methods 
 
        /// 
        /// Searches for an array in the cache. 
        /// 
        /// 
        /// Minimum number of elements in the array.
        ///  
        /// 
        /// Specifies the type of array. 
        ///  
        /// 
        /// A matching array if present, otherwise null. 
        /// 
        private static Array GetBuffer(int length, int index)
        {
            Array buffer = null; 

            if (Interlocked.Increment(ref _mutex) == 1) 
            { 
                if (_buffers != null &&
                    _buffers[index] != null && 
                    length <= _buffers[index].Length)
                {
                    buffer = _buffers[index];
                    _buffers[index] = null; 
                }
            } 
            Interlocked.Decrement(ref _mutex); 

            return buffer; 
        }

        /// 
        /// Takes ownership of an array. 
        /// 
        ///  
        /// The array.  May be null. 
        /// 
        ///  
        /// Specifies the type of array.
        /// 
        private static void ReleaseBuffer(Array buffer, int index)
        { 
            if (buffer != null)
            { 
                if (Interlocked.Increment(ref _mutex) == 1) 
                {
                    if (_buffers == null) 
                    {
                        _buffers = new Array[BuffersLength];
                    }
 
                    if (_buffers[index] == null ||
                        (_buffers[index].Length < buffer.Length && buffer.Length <= MaxBufferLength)) 
                    { 
                        _buffers[index] = buffer;
                    } 
                }
                Interlocked.Decrement(ref _mutex);
            }
        } 

        #endregion Private Methods 
 
        //------------------------------------------------------
        // 
        //  Private Fields
        //
        //------------------------------------------------------
 
        #region Private Fields
 
        // Max number of elements in any cached array.  If a request if made for a larger array 
        // it will always be allocated from the heap.
        private const int MaxBufferLength = 1024; 

        // Indices in _buffers for each supported type.
        private const int GlyphMetricsIndex         = 0;
        private const int UIntsIndex                = 1; 
        private const int UShortsIndex              = 2;
        private const int BuffersLength             = 3; 
 
        // Guards access to _buffers.
        static private long _mutex; 

        // Array of cached arrays, one bucker per supported type.
        // Currently, we cache just one array per type.  A more general cache would hold N byte arrays.
        // However, we don't currently have any scenarios that hold more than one array of the same type 
        // or more than two arrays of different types at the same time, so it is difficult to justify
        // making the implementation more complex.  ComputeTypographyAvailabilities could benefit from 
        // a more general cache (UnicodeRange.GetFullRange could use a cached array), but the savings 
        // in profiled scenarios are small, ~16k for MSNBaml.exe.  If we find a more compelling
        // scenario a change might be worthwhile. 
        static private Array[] _buffers;

        #endregion Private Fields
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
// -------------------------------------------------------------------------- 
//
// File: BufferCache.cs
//
// Copyright (C) Microsoft Corporation.  All rights reserved. 
//
// Description: BufferCache class implementation. 
// 
//---------------------------------------------------------------------------
 
using System;
using System.Threading;
using MS.Internal.Text.TextInterface;
 
namespace MS.Internal.FontCache
{ 
    ///  
    /// A static, thread safe array cache used to minimize heap allocations.
    ///  
    /// 
    /// Cached arrays are not zero initialized, and they may be larger than
    /// the requested number of elements.
    ///  
    internal static class BufferCache
    { 
        //----------------------------------------------------- 
        //
        //  Internal Methods 
        //
        //-----------------------------------------------------

        #region Internal Methods 

        ///  
        /// Attempts to release all allocated memory.  Has no effect if the cache 
        /// is locked by another thread.
        ///  
        internal static void Reset()
        {
            if (Interlocked.Increment(ref _mutex) == 1)
            { 
                _buffers = null;
            } 
            Interlocked.Decrement(ref _mutex); 
        }
 
        /// 
        /// Returns a GlyphMetrics[].
        /// 
        ///  
        /// Minimum number of elements in the array.
        ///  
        internal static GlyphMetrics[] GetGlyphMetrics(int length) 
        {
            GlyphMetrics[] glyphMetrics = (GlyphMetrics[])GetBuffer(length, GlyphMetricsIndex); 

            if (glyphMetrics == null)
            {
                glyphMetrics = new GlyphMetrics[length]; 
            }
 
            return glyphMetrics; 
        }
 
        /// 
        /// Releases a previously allocated GlyphMetrics[], possibly adding it
        /// to the cache.
        ///  
        /// 
        /// It is not strictly necessary to call this method after receiving an 
        /// array.  The penalty is the performance hit of doing a heap allocation 
        /// on the next request if this method is not called.
        ///  
        internal static void ReleaseGlyphMetrics(GlyphMetrics[] glyphMetrics)
        {
            ReleaseBuffer(glyphMetrics, GlyphMetricsIndex);
        } 

        ///  
        /// Returns a ushort[]. 
        /// 
        ///  
        /// Minimum number of elements in the array.
        /// 
        internal static ushort[] GetUShorts(int length)
        { 
            ushort[] ushorts = (ushort[])GetBuffer(length, UShortsIndex);
 
            if (ushorts == null) 
            {
                ushorts = new ushort[length]; 
            }

            return ushorts;
        } 

        ///  
        /// Releases a previously allocated ushort[], possibly adding it 
        /// to the cache.
        ///  
        /// 
        /// It is not strictly necessary to call this method after receiving an
        /// array.  The penalty is the performance hit of doing a heap allocation
        /// on the next request if this method is not called. 
        /// 
        internal static void ReleaseUShorts(ushort[] ushorts) 
        { 
            ReleaseBuffer(ushorts, UShortsIndex);
        } 

        /// 
        /// Returns a uint[].
        ///  
        /// 
        /// Minimum number of elements in the array. 
        ///  
        internal static uint[] GetUInts(int length)
        { 
            uint[] uints = (uint[])GetBuffer(length, UIntsIndex);

            if (uints == null)
            { 
                uints = new uint[length];
            } 
 
            return uints;
        } 

        /// 
        /// Releases a previously allocated uint[], possibly adding it
        /// to the cache. 
        /// 
        ///  
        /// It is not strictly necessary to call this method after receiving an 
        /// array.  The penalty is the performance hit of doing a heap allocation
        /// on the next request if this method is not called. 
        /// 
        internal static void ReleaseUInts(uint[] uints)
        {
            ReleaseBuffer(uints, UIntsIndex); 
        }
 
        #endregion Internal Methods 

        //------------------------------------------------------ 
        //
        //  Private Methods
        //
        //----------------------------------------------------- 

        #region Private Methods 
 
        /// 
        /// Searches for an array in the cache. 
        /// 
        /// 
        /// Minimum number of elements in the array.
        ///  
        /// 
        /// Specifies the type of array. 
        ///  
        /// 
        /// A matching array if present, otherwise null. 
        /// 
        private static Array GetBuffer(int length, int index)
        {
            Array buffer = null; 

            if (Interlocked.Increment(ref _mutex) == 1) 
            { 
                if (_buffers != null &&
                    _buffers[index] != null && 
                    length <= _buffers[index].Length)
                {
                    buffer = _buffers[index];
                    _buffers[index] = null; 
                }
            } 
            Interlocked.Decrement(ref _mutex); 

            return buffer; 
        }

        /// 
        /// Takes ownership of an array. 
        /// 
        ///  
        /// The array.  May be null. 
        /// 
        ///  
        /// Specifies the type of array.
        /// 
        private static void ReleaseBuffer(Array buffer, int index)
        { 
            if (buffer != null)
            { 
                if (Interlocked.Increment(ref _mutex) == 1) 
                {
                    if (_buffers == null) 
                    {
                        _buffers = new Array[BuffersLength];
                    }
 
                    if (_buffers[index] == null ||
                        (_buffers[index].Length < buffer.Length && buffer.Length <= MaxBufferLength)) 
                    { 
                        _buffers[index] = buffer;
                    } 
                }
                Interlocked.Decrement(ref _mutex);
            }
        } 

        #endregion Private Methods 
 
        //------------------------------------------------------
        // 
        //  Private Fields
        //
        //------------------------------------------------------
 
        #region Private Fields
 
        // Max number of elements in any cached array.  If a request if made for a larger array 
        // it will always be allocated from the heap.
        private const int MaxBufferLength = 1024; 

        // Indices in _buffers for each supported type.
        private const int GlyphMetricsIndex         = 0;
        private const int UIntsIndex                = 1; 
        private const int UShortsIndex              = 2;
        private const int BuffersLength             = 3; 
 
        // Guards access to _buffers.
        static private long _mutex; 

        // Array of cached arrays, one bucker per supported type.
        // Currently, we cache just one array per type.  A more general cache would hold N byte arrays.
        // However, we don't currently have any scenarios that hold more than one array of the same type 
        // or more than two arrays of different types at the same time, so it is difficult to justify
        // making the implementation more complex.  ComputeTypographyAvailabilities could benefit from 
        // a more general cache (UnicodeRange.GetFullRange could use a cached array), but the savings 
        // in profiled scenarios are small, ~16k for MSNBaml.exe.  If we find a more compelling
        // scenario a change might be worthwhile. 
        static private Array[] _buffers;

        #endregion Private Fields
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK