您当前的位置: 首页 >  c#

Jave.Lin

暂无认证

  • 4浏览

    0关注

    704博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

环形队列缓存(C#版)

Jave.Lin 发布时间:2017-12-28 18:26:40 ,浏览量:4

代码
        /// 不要给下面代码长度吓到啊,因为些的测试用列的代码比较多,下面的CircleQueue代码还是不多的
        /// 
        /// author : jave.lin
        /// date : 2017-12-28
        /// 
        static void Main(string[] args)
        {
            // 测试环形缓存
            _testingCircleQueue();
        }

        #region 环形缓存队列

        private static void _testingCircleQueue()
        {
            // 测试写入到满为止
            //_testingWriteFull();
            // 测试读取到空为止
            //_testingReadEmpty();
            // 测试读写平衡
            //_testingWriteReadBalance();

            // 批量测试写入到满为止
            //_testingWriteFullRange();
            // 批量测试读取到空为止
            //_testingReadEmptyRange();
            // 批量测试读写平衡
            //_testingWriteReadBalanceRange();

            var r = new Random();
            var cq = new CircleQueue(10);
            for (int i = 0, len = cq.len; i < len; ++i)
            {
                cq.write(r.Next(len));
            }

            Console.WriteLine("cq:" + cq);

            var opBuff = new int[cq.len];
            for (int i = 0, len = cq.len / 3; i < 3; ++i)
            {
                cq.readRange(opBuff, 0, len);
                Console.WriteLine("opBuff:" + string.Join(",", opBuff));
                Console.WriteLine("cq:" + cq);
            }

            cq.readRange(opBuff);
            Console.WriteLine("opBuff:" + string.Join(",", opBuff));
            Console.WriteLine("cq:" + cq);

            Console.ReadLine();
        }

        private static void _testingWriteReadBalance()
        {
            var r = new Random();
            var size = 10;
            var circileBuff = new CircleQueue(size);
            Console.WriteLine("buff size:" + size);
            while (circileBuff.full() == false)
            {
                var writeRet = circileBuff.write(r.Next(10));
                if (writeRet == 0)
                {
                    Console.WriteLine("write full, break");
                    break;
                }
                writeRet = circileBuff.write(r.Next(10));
                if (writeRet == 0)
                {
                    Console.WriteLine("write full, break");
                    break;
                }
                Console.WriteLine("write byte, buff : " + circileBuff);
                var readValue = 0;
                circileBuff.read(ref readValue);
                var readFlag = circileBuff.read(ref readValue);
                if (readFlag != 0)
                {
                    Console.WriteLine("read byte, buff : " + circileBuff);
                }
                else
                {
                    Console.WriteLine("read failure, buff empty");
                }

                Thread.Sleep(1000);
            }
            Console.WriteLine("buff full:" + circileBuff);
            Console.ReadLine();
        }
        private static void _testingReadEmpty()
        {
            var r = new Random();
            var size = 10;
            var circileBuff = new CircleQueue(size);
            Console.WriteLine("buff size:" + size);
            while (circileBuff.full() == false)
            {
                circileBuff.write(r.Next(10));
            }
            while (circileBuff.empty() == false)
            {
                var readValue = 0;
                circileBuff.read(ref readValue);
                var readFlag = circileBuff.read(ref readValue);
                if (readFlag != 0)
                {
                    Console.WriteLine("read byte, buff : " + circileBuff);
                }
                else
                {
                    Console.WriteLine("read failure, buff empty");
                    break;
                }
                circileBuff.write(r.Next(10));
                Console.WriteLine("write byte, buff : " + circileBuff);

                Thread.Sleep(1000);
            }
            Console.WriteLine("buff empy():" + circileBuff);
            Console.ReadLine();
        }
        private static void _testingWriteFull()
        {
            var r = new Random();
            var size = 10;
            var circileBuff = new CircleQueue(size);
            Console.WriteLine("buff size:" + size);
            while (circileBuff.full() == false)
            {
                var writeRet = circileBuff.write(r.Next(10));
                if (writeRet == 0)
                {
                    Console.WriteLine("write full, break");
                    break;
                }
                writeRet = circileBuff.write(r.Next(10));
                if (writeRet == 0)
                {
                    Console.WriteLine("write full, break");
                    break;
                }
                Console.WriteLine("write byte, buff : " + circileBuff);
                var readValue = 0;
                var readFlag = circileBuff.read(ref readValue);
                if (readFlag != 0)
                {
                    Console.WriteLine("read byte, buff : " + circileBuff);
                }
                else
                {
                    Console.WriteLine("read failure, buff empty");
                }

                Thread.Sleep(1000);
            }
            Console.WriteLine("buff full:" + circileBuff);
            Console.ReadLine();
        }

        private static void _testingWriteReadBalanceRange()
        {
            var r = new Random();
            var size = 10;
            var circileBuff = new CircleQueue(size);
            Console.WriteLine("buff size:" + size);
            var opBuff = new int[2];
            while (circileBuff.full() == false)
            {
                opBuff[0] = r.Next(10);
                opBuff[1] = r.Next(10);
                var writeRet = circileBuff.writeRange(opBuff);
                if (writeRet == 0)
                {
                    Console.WriteLine("write full, break");
                    break;
                }
                Console.WriteLine("write byte, buff : " + circileBuff);
                var readFlag = circileBuff.readRange(opBuff);
                if (readFlag != 0)
                {
                    Console.WriteLine("read byte, buff : " + circileBuff);
                }
                else
                {
                    Console.WriteLine("read failure, buff empty");
                }

                Thread.Sleep(1000);
            }
            Console.WriteLine("buff full:" + circileBuff);
            Console.ReadLine();
        }
        private static void _testingReadEmptyRange()
        {
            var r = new Random();
            var size = 10;
            var circileBuff = new CircleQueue(size);
            Console.WriteLine("buff size:" + size);
            while (circileBuff.full() == false)
            {
                circileBuff.write(r.Next(10));
            }
            var opBuff = new int[2];
            while (circileBuff.empty() == false)
            {
                var readFlag = circileBuff.readRange(opBuff, 0, 2);
                if (readFlag != 0)
                {
                    Console.WriteLine("read byte, buff : " + circileBuff);
                }
                else
                {
                    Console.WriteLine("read failure, buff empty");
                    break;
                }
                circileBuff.write(r.Next(10));
                Console.WriteLine("write byte, buff : " + circileBuff);

                Thread.Sleep(1000);
            }
            Console.WriteLine("buff empy():" + circileBuff);
            Console.ReadLine();
        }
        private static void _testingWriteFullRange()
        {
            var r = new Random();
            var size = 10;
            var circileBuff = new CircleQueue(size);
            Console.WriteLine("buff size:" + size);

            var opBuff = new int[] { 0, 0 };

            while (circileBuff.full() == false)
            {
                opBuff[0] = r.Next(10);
                opBuff[1] = r.Next(10);

                var writeRet = circileBuff.writeRange(opBuff);
                if (writeRet == 0)
                {
                    Console.WriteLine("write full, break");
                    break;
                }
                Console.WriteLine("write byte, buff : " + circileBuff);
                var readValue = 0;
                var readFlag = circileBuff.read(ref readValue);
                if (readFlag != 0)
                {
                    Console.WriteLine("read byte, buff : " + circileBuff);
                }
                else
                {
                    Console.WriteLine("read failure, buff empty");
                }

                Thread.Sleep(1000);
            }
            Console.WriteLine("buff full:" + circileBuff);
            Console.ReadLine();
        }

        /// 
        /// author : jave.lin
        /// date : 2017-12-28
        /// 
        /// 
        class CircleQueue
        {
            private T[] _m_pBuff;

            private int _m_iLen;

            private int _m_iHeadIdex; // head, trail
            private int _m_iTrailIdx;
            private bool _m_bCircle; // 是否折回了,trail < head

            private object _m_pLockObj = new object();

            public T[] buff
            {
                get { return _m_pBuff; }
            }

            public int len
            {
                get { return _m_iLen; }
            }

            public CircleQueue( int len )
            {
                _m_iLen = len;
                if ( _m_iLen < 2)
                {
                    throw new Exception("CircleQueue invalidted len : " + len);
                }
                _m_pBuff = new T[len];
            }

            public override string ToString()
            {
                return "size:" + _m_iLen + ", h:" + _m_iHeadIdex + ", t:" + _m_iTrailIdx + ", c:" + _m_bCircle + ", frc:" + freeCount() + ", buff:" + string.Join(",", _m_pBuff);
            }
            public int freeCount()
            {
                if (_m_bCircle)
                {
                    return _m_iHeadIdex - _m_iTrailIdx;
                }
                else
                {
                    return _m_iHeadIdex + (_m_iLen - _m_iTrailIdx);
                }
            }

            public int fillCount()
            {
                return _m_iLen - freeCount();
            }

            public bool full()
            {
                return freeCount() == 0;
            }
            public bool empty()
            {
                return freeCount() == _m_iLen;
            }
            public int readSafe(ref T result)
            {
                lock (_m_pLockObj)
                {
                    return read(ref result);
                }
            }
            public int read(ref T result)
            {
                if (empty()) return 0;
                result = _m_pBuff[_m_iHeadIdex];
                _m_iHeadIdex++;
                if (_m_bCircle)
                {
                    if (_m_iHeadIdex == _m_iLen)
                    {
                        _m_iHeadIdex = 0;
                        _m_bCircle = false;
                    }
                    else if (_m_iHeadIdex == _m_iTrailIdx)
                    {
                        _m_bCircle = false;
                    }
                }
                return 1;
            }
            public int readRangeSafe(int[] result, int resultStartIdx = 0, int readLen = 0, bool autoFitLen = true)
            {
                lock (_m_pLockObj)
                {
                    return readRange(result, resultStartIdx, readLen, autoFitLen);
                }
            }
            public int readRange( int[] result, int resultStartIdx = 0, int readLen = 0, bool autoFitLen = true )
            {
                var fc = fillCount();
                if (autoFitLen == false)
                {
                    if (result.Length < readLen)
                    {
                        throw new Exception("popTopRang result not enough capacity, result.len:" + result.Length + ", popLen:" + readLen);
                    }
                }
                else
                {
                    if (readLen  _m_iLen )
                {
                    throw new Exception("popTopRange popLen to large : " + readLen + ", and buffLen : " + _m_iLen);
                }
                if (readLen == 0 || fc == 0 )
                {
                    return 0;
                }
                if (readLen > fc)
                {
                    return 0;
                }
                if (autoFitLen == false)
                {
                    if (fc > _m_iLen)
                    {
                        throw new Exception("popTopRange popLen to large : " + readLen + ", and fillCount : " + _m_iLen);
                    }
                }
                else
                {
                    if (_m_bCircle ) // 如果有折回过,需要特殊处理
                    {
                        var remainLenInRight = _m_iLen - _m_iHeadIdex; // 右边剩余的数量
                        if (remainLenInRight = _m_iLen)
                {
                    _m_bCircle = false;
                    _m_iHeadIdex %= _m_iLen;
                }
                return readLen;
            }

            public int writeSafe( T v )
            {
                lock (_m_pLockObj)
                {
                    return write(v);
                }
            }
            public int write( T v )
            {
                if ( _m_bCircle ) // 折回过
                {
                    if (_m_iTrailIdx == _m_iHeadIdex) // 已满
                    {
                        return 0;
                    }
                    _m_pBuff[_m_iTrailIdx] = v;
                    _m_iTrailIdx = _m_iTrailIdx + 1;
                }
                else // 没折回过
                {
                    _m_pBuff[_m_iTrailIdx] = v;
                    _m_iTrailIdx = _m_iTrailIdx + 1;
                }
                if (_m_iTrailIdx == _m_iLen) // 折回
                {
                    _m_iTrailIdx = 0;
                    _m_bCircle = true;
                }
                return 1;
            }
            public int writeRangeSafe(int[] data, int startDataIdx = 0, int writeLen = 0)
            {
                lock (_m_pLockObj)
                {
                    return writeRange(data, startDataIdx, writeLen);
                }
            }
            public int writeRange( int[] data, int startDataIdx = 0, int writeLen = 0 )
            {
                if ( writeLen == 0 )
                {
                    writeLen = data.Length;
                }

                if ( freeCount() < writeLen )
                {
                    return 0; // overload buff
                }

                if ( _m_bCircle ) // 折回过
                {
                    Array.Copy(data, startDataIdx, _m_pBuff, _m_iTrailIdx, writeLen);
                    _m_iTrailIdx += writeLen;
                    _m_iTrailIdx %= _m_iLen;
                }
                else // 未折回过
                {
                    var remainFreeLen = _m_iLen - _m_iTrailIdx;
                    if (remainFreeLen buff.len时,并重置回0时,标记circle=true
  • 当head>buff.len时,并重置回0时,标记circle=false
  • 获取当前可写长度:return circle ? head-trail : head + ( len - trail);
  • 应用
    • 用在想在数据流(内存)利用率比较高的场合会使用到
    • 写入、读取的速度相当时最佳,可以无限的稳定使用
    • 在下位机会更多的使用,毕竟资源比较珍贵
    • 否则使用一个大一些的buff来存数据流,在用另一个appliedBuff一次性读取完所有buff中的数据,下次写入buff是就从0开始写入就好了
    关注
    打赏
    1664331872
    查看更多评论
    0.0921s