#if !USE_CUSTOM_VSTRING_SCRIPT

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace Giant.Common
{
/// <summary>
/// 内存块集：包含多个大小相等的内存块
/// </summary>
internal sealed class MemoryBlock
    {
        /// <summary>
        /// unused memory list
        /// </summary>
        private Queue<Int64> m_FreeMemory;



        /// <summary>
        /// used memory list
        /// </summary>
        private HashSet<Int64> m_UsedMemory;



        /// <summary>
        /// head of this memory block
        /// </summary>
        private Int64 m_Head;



        /// <summary>
        /// tail of this memory block
        /// </summary>
        private Int64 m_Tail;



        /// <summary>
        /// total count of this memory block
        /// </summary>
        private int m_Count;
        public int Count
        {
            get { return m_Count; }
        }



        /// <summary>
        /// block size
        /// </summary>
        private int m_Size;



        /// <summary>
        /// Init block memory
        /// </summary>
        public void Init(Int64 _Start, int _Size, int _Count)
        {
            m_FreeMemory    = new Queue<Int64>(_Count);
            m_UsedMemory    = new HashSet<Int64>();
            m_Count         = _Count;
            m_Size          = _Size;
            m_Head          = _Start;

            Int64 tP = m_Head;
            for (int tIdx = 0; tIdx < _Count; ++tIdx)
            {
                m_FreeMemory.Enqueue(tP);
                tP += _Size;
            }
            m_Tail = m_Head + _Size * _Count;
        }



        /// <summary>
        /// Gets total memory
        /// </summary>
        public int GetTotalMemory()
        {
            return m_Count * m_Size;
        }



        /// <summary>
        /// Free memory to block
        /// </summary>
        public void FreeMemory(ref IntPtr _Ptr)
        {
            Int64 tP = _Ptr.ToInt64();
            if (tP >= m_Head && tP < m_Tail)
            {
                if(m_UsedMemory.Remove(tP))
                    m_FreeMemory.Enqueue(tP);
            }
            else
                Marshal.FreeHGlobal(_Ptr);
        }



        /// <summary>
        /// Gets memory from block
        /// </summary>
        public Int64 AllocMemory()
        {
            if (m_FreeMemory.Count > 0)
            {
                Int64 tP = m_FreeMemory.Dequeue();
                m_UsedMemory.Add(tP);
                return tP;
            }
            return Marshal.AllocHGlobal(m_Size).ToInt64();
        }



#if !RELEASE
        /// <summary>
        /// debug memory info
        /// </summary>
        public string GetSizeInfo()
        {
            return string.Format("    【Pool_{0}】Total:{1}, Unused:{2}，Used:{3};", m_Size / 2, m_Count * m_Size, m_FreeMemory.Count * m_Size, m_UsedMemory.Count * m_Size);
        }
#endif
    }
}
#endif