//==============================================================
//  Copyright (C) 2020  Inc. All rights reserved.
//
//==============================================================
//  Create by 种道洋 at 2020/9/23 8:39:17.
//  Version 1.0
//  种道洋
//==============================================================

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DBRuntime.His
{
    public class ManualHisDataMemoryBlockPool
    {

        #region ... Variables  ...
        /// <summary>
        /// 
        /// </summary>
        public static ManualHisDataMemoryBlockPool Pool = new ManualHisDataMemoryBlockPool();

        /// <summary>
        /// 
        /// </summary>
        private Dictionary<int, Queue<ManualHisDataMemoryBlock>> mFreePools = new Dictionary<int, Queue<ManualHisDataMemoryBlock>>();

        #endregion ...Variables...

        #region ... Events     ...

        #endregion ...Events...

        #region ... Constructor...

        #endregion ...Constructor...

        #region ... Properties ...

        #endregion ...Properties...

        #region ... Methods    ...

        /// <summary>
        /// 
        /// </summary>
        /// <param name="size"></param>
        public void PreAlloc(int size)
        {
            lock (mFreePools)
            {
                if (mFreePools.ContainsKey(size))
                {
                    var pp = mFreePools[size];
                    var bnb = NewBlock(size);
                    pp.Enqueue(bnb);
                }
                else
                {
                    var bnb = NewBlock(size);
                    Queue<ManualHisDataMemoryBlock> dd = new Queue<ManualHisDataMemoryBlock>();
                    dd.Enqueue(bnb);
                    mFreePools.Add(size,dd);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="size"></param>
        /// <returns></returns>
        public ManualHisDataMemoryBlock Get(int size)
        {
            lock (mFreePools)
            {
                if (mFreePools.ContainsKey(size))
                {
                    var pp = mFreePools[size];
                    if (pp.Count > 0)
                    {
                        var bnb = pp.Dequeue();
                        return bnb;
                    }
                    else
                    {
                        var bnb = NewBlock(size);
                        return bnb;
                    }
                }
                else
                {
                    var bnb = NewBlock(size);
                    Queue<ManualHisDataMemoryBlock> dd = new Queue<ManualHisDataMemoryBlock>();
                    mFreePools.Add(size, dd);
                    return bnb;
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="size"></param>
        /// <returns></returns>
        private ManualHisDataMemoryBlock NewBlock(int size)
        {
            return new ManualHisDataMemoryBlock(size);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="block"></param>

        public void Release(ManualHisDataMemoryBlock block)
        {
            lock (mFreePools)
            {
                var size = (int)block.AllocSize;
                if (mFreePools.ContainsKey(size))
                {
                    var vv = mFreePools[size];
                    vv.Enqueue(block);
                    block.Clear();
                }
            }
        }

        #endregion ...Methods...

        #region ... Interfaces ...

        #endregion ...Interfaces...
    }
}
