示例#1
0
        /// <summary>
        /// Loads a tree from a byte buffer created by the Serialize function.
        /// </summary>
        /// <param name="data">Data to load into the tree.</param>
        /// <param name="pool">Pool to use to create the tree.</param>
        public Tree(Span <byte> data, BufferPool pool)
        {
            if (data.Length <= 4)
            {
                throw new ArgumentException($"Data is only {data.Length} bytes long; that's too small for even a header.");
            }
            leafCount = Unsafe.As <byte, int>(ref data[0]);
            nodeCount = leafCount - 1;
            var       leafByteCount       = leafCount * sizeof(Leaf);
            var       nodeByteCount       = nodeCount * sizeof(Node);
            var       metanodeByteCount   = nodeCount * sizeof(Metanode);
            const int leavesStartIndex    = 4;
            var       nodesStartIndex     = leavesStartIndex + leafByteCount;
            var       metanodesStartIndex = nodesStartIndex + nodeByteCount;

            if (data.Length < leavesStartIndex + leafByteCount + nodeByteCount + metanodeByteCount)
            {
                throw new ArgumentException($"Header suggested there were {leafCount} leaves, but there's not enough room in the data for that.");
            }
            pool.Take(leafCount, out Leaves);
            pool.Take(nodeCount, out Nodes);
            pool.Take(nodeCount, out Metanodes);
            leaves    = Leaves.Memory;
            nodes     = Nodes.Memory;
            metanodes = Metanodes.Memory;
            Unsafe.CopyBlockUnaligned(ref *(byte *)leaves, ref data[leavesStartIndex], (uint)leafByteCount);
            Unsafe.CopyBlockUnaligned(ref *(byte *)nodes, ref data[nodesStartIndex], (uint)nodeByteCount);
            Unsafe.CopyBlockUnaligned(ref *(byte *)metanodes, ref data[metanodesStartIndex], (uint)metanodeByteCount);
        }
示例#2
0
        /// <summary>
        /// Resizes the buffers backing the tree's nodes and leaves. Will not shrink the buffers below the size needed by the currently resident nodes and leaves.
        /// </summary>
        /// <param name="pool">Pool from which to take and return resources.</param>
        /// <param name="targetLeafSlotCount">The desired number of available leaf slots.</param>
        public void Resize(BufferPool pool, int targetLeafSlotCount)
        {
            //Note that it's not safe to resize below the size of potentially used leaves. If the user wants to go smaller, they'll need to explicitly deal with the leaves somehow first.
            var leafCapacityForTarget = BufferPool.GetCapacityForCount <Leaf>(Math.Max(leafCount, targetLeafSlotCount));
            //Adding incrementally checks the capacity of leaves, and issues a resize if there isn't enough space. But it doesn't check nodes.
            //You could change that, but for now, we simply ensure that the node array has sufficient room to hold everything in the resized leaf array.
            var  nodeCapacityForTarget     = BufferPool.GetCapacityForCount <Node>(Math.Max(nodeCount, leafCapacityForTarget - 1));
            var  metanodeCapacityForTarget = BufferPool.GetCapacityForCount <Metanode>(Math.Max(nodeCount, leafCapacityForTarget - 1));
            bool wasAllocated = Leaves.Allocated;

            Debug.Assert(Leaves.Allocated == Nodes.Allocated);
            if (leafCapacityForTarget != Leaves.Length)
            {
                pool.ResizeToAtLeast(ref Leaves, leafCapacityForTarget, leafCount);
                leaves = Leaves.Memory;
            }
            if (nodeCapacityForTarget != Nodes.Length)
            {
                pool.ResizeToAtLeast(ref Nodes, nodeCapacityForTarget, nodeCount);
                nodes = Nodes.Memory;
            }
            if (metanodeCapacityForTarget != Metanodes.Length)
            {
                pool.ResizeToAtLeast(ref Metanodes, metanodeCapacityForTarget, nodeCount);
                //A node's RefineFlag must be 0, so just clear out the node set.
                //TODO: This won't be necessary if we get rid of refineflags as a concept.
                Metanodes.Clear(nodeCount, Nodes.Length - nodeCount);
                metanodes = Metanodes.Memory;
            }
            if (!wasAllocated)
            {
                InitializeRoot();
            }
        }