/// <summary>
        ///     Worst: O(4 log n)
        /// </summary>
        public long Alloc(long length)
        {
            if (length <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            if (m_avail.Count > 0)
            {
                // search for an available memory segment of at least length bytes, returning the smallest result that is >= length
                var res = m_avail.BinarySearch_GreaterOrEqualTo(new MemorySegment(0, length), CompareMemorySegmentsSizeOnly);

                if (res.Diff <= 0)  // if available_memory_segment >= length
                {
                    var x   = res.Node.Key;
                    var bsr = m_availAddresses.BinarySearch(x.Address);
                    if (bsr.Index < 0)
                    {
                        bsr = bsr.BitwiseNot();
                    }

                    m_avail.Remove(res.Node);
                    var address = x.Address;
                    x = new MemorySegment(address + length, x.Length - length);
                    res.Node.UpdateKey(x);
                    this.TotalFree -= length;

                    if (x.Length > 0)
                    {
                        bsr.Update(x.Address, x.Length);
                        m_avail.Add(x);
                    }
                    else
                    {
                        m_availAddresses.Remove(bsr);
                    }

                    return(address);
                }
            }

            // if theres not enough consecutive memory, then add at the end
            var end = this.Capacity;

            this.Capacity = end + length;

            return(end);
        }
        /// <summary>
        ///     Worst: O(4 log n)
        /// </summary>
        public long Alloc(long length)
        {
            if (length <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            if (m_avail.Count > 0)
            {
                var res = m_avail.BinarySearch(new MemorySegment(0, length), CompareMemorySegmentsSizeOnly);

                if (res.Diff < 0)
                {
                    var x   = res.Node.Key;
                    var bsr = m_availAddresses.BinarySearch(x.Address);
                    if (bsr.Index < 0)
                    {
                        bsr = bsr.BitwiseNot();
                    }

                    m_avail.Remove(res.Node);
                    var address = x.Address;
                    x.Address       = address + length;
                    x.Length       -= length;
                    this.TotalFree -= length;

                    if (x.Length > 0)
                    {
                        bsr.Update(x.Address, x.Length);
                        m_avail.Add(x);
                    }
                    else
                    {
                        m_availAddresses.Remove(bsr);
                    }

                    return(address);
                }
            }

            // if theres not enough consecutive memory, then add at the end
            var end = this.Capacity;

            this.Capacity = end + length;

            return(end);
        }