Exemple #1
0
        /// <summary>
        /// Writes the structure to the next available node for writing.
        /// </summary>
        /// <typeparam name="T">The structure type to be written.</typeparam>
        /// <param name="source">The structure to be written.</param>
        /// <param name="timeout">The maximum number of milliseconds to wait for a node to become available for writing. Defaults to 1000 (ms).</param>
        /// <exception cref="ArgumentOutOfRangeException">The size of the <typeparamref name="T"/> structure is larger than <see cref="NodeBufferSize"/>.</exception>
        /// <returns>The number of bytes written. The value is larger than zero if successful.</returns>
        public virtual int Write <T>(ref T source, int timeout = 1000)
            where T : struct
        {
            int structSize = Polyfill.GetMarshalSizeOf <T>();

            if (structSize > NodeBufferSize)
            {
                throw new ArgumentOutOfRangeException("T", string.Format(RS.StructureSizeGtNodeBufferSize, typeof(T).Name));
            }

            // Attempt to retrieve a node for writing
            Node *node = GetNodeForWriting(timeout);

            if (node == null)
            {
                return(0);
            }

            // Copy the data using the MemoryMappedViewAccessor
            base.Write <T>(ref source, node->Offset);
            node->AmountWritten = structSize;

            // Return the node for further writing
            PostNode(node);

            return(structSize);
        }
Exemple #2
0
        public void AddAfter(T value)
        {
            if (_count > 0)
            {
                Node *nextPtr = (Node *)Marshal.AllocHGlobal(sizeof(Node));
                nextPtr->Value = value;

                _tail->Next = nextPtr;
                _tail       = nextPtr;
            }
            else if (_head == null)
            {
                Node *nextPtr = (Node *)Marshal.AllocHGlobal(sizeof(Node));
                nextPtr->Value = value;

                _head = nextPtr;
                _tail = nextPtr;
            }
            else // 减少一次内存分配
            {
                _head->Value = value;
                _tail        = _head;
            }

            _count++;
        }
Exemple #3
0
        /// <summary>
        /// Reads the next available node for reading into the a structure.
        /// </summary>
        /// <typeparam name="T">The structure type to be read.</typeparam>
        /// <param name="destination">The resulting structure, if successful. Otherwise, `default(T)`.</param>
        /// <param name="timeout">The maximum number of milliseconds to wait for a node to become available for reading. Defaults to 1000 (ms).</param>
        /// <exception cref="ArgumentOutOfRangeException">If the size of <typeparamref name="T"/> is larger than <see cref="NodeBufferSize"/>.</exception>
        /// <returns>The number of bytes read.</returns>
        public virtual int Read <T>(out T destination, int timeout = 1000)
            where T : struct
        {
            int structSize = Polyfill.GetMarshalSizeOf <T>();

            if (structSize > NodeBufferSize)
            {
                throw new ArgumentOutOfRangeException("T", string.Format(RS.StructureSizeGtNodeBufferSize, typeof(T).Name));
            }

            // Attempt to retrieve a node
            Node *node = GetNodeForReading(timeout);

            if (node == null)
            {
                destination = default(T);
                return(0);
            }

            // Copy the data using the MemoryMappedViewAccessor
            base.Read <T>(out destination, node->Offset);

            // Return the node for further writing
            ReturnNode(node);

            return(structSize);
        }
Exemple #4
0
        public void ITdel()
        {
            int dd = 0;

            if (second == _second)
            {
                dd = 1;
            }
            if (second == _first)
            {
                dd = 2;
            }
            Node *p0 = _prev(first, second);
            Node *p1 = _next(first, second);
            Node *p2 = _next(second, p1);

            Marshal.FreeHGlobal((IntPtr)second);
            (*first).xorLink = _ptrXor(p0, p1);
            (*p1).xorLink    = _ptrXor(first, p2);
            second           = p1;
            if (dd == 1)
            {
                _second = p1;
            }
            if (dd == 2)
            {
                _first  = p1;
                _second = p2;
            }
        }
        protected virtual Node *GetNodeForReading(int timeout)
        {
            for (; ;)
            {
                int   blockIndex = _nodeHeader->ReadStart;
                Node *node       = this[blockIndex];
                if (blockIndex == _nodeHeader->WriteEnd)
                {
                    // No data is available, wait for it
                    if (DataExists.WaitOne(timeout))
                    {
                        continue;
                    }

                    // Timeout
                    return(null);
                }

                #pragma warning disable 0420 // ignore ref to volatile warning - Interlocked API
                if (Interlocked.CompareExchange(ref _nodeHeader->ReadStart, node->Next, blockIndex) == blockIndex)
                {
                    return(node);
                }
                #pragma warning restore 0420

                // Another thread has already acquired this node for reading, try again
                continue;
            }
        }
        public unsafe Chunk *GetChunkWithEmptySlots(int *sharedComponentDataIndices, int numSharedComponents)
        {
            uint  hashCode = this.GetHashCode(sharedComponentDataIndices, numSharedComponents);
            Node *buckets  = this.buckets + ((hashCode & this.hashMask) * sizeof(Node));
            Node *nodePtr2 = this.buckets + (this.hashMask * sizeof(Node));

            while (true)
            {
                Chunk *chunkFromEmptySlotNode;
                if (buckets.IsFree())
                {
                    chunkFromEmptySlotNode = null;
                }
                else
                {
                    if (!(!buckets.IsDeleted() && buckets.CheckEqual(hashCode, sharedComponentDataIndices, numSharedComponents)))
                    {
                        buckets++;
                        if (buckets <= nodePtr2)
                        {
                            continue;
                        }
                        buckets = this.buckets;
                        continue;
                    }
                    chunkFromEmptySlotNode = ArchetypeManager.GetChunkFromEmptySlotNode(buckets->list.Begin);
                }
                return(chunkFromEmptySlotNode);
            }
        }
Exemple #7
0
        public int?RemoveAt(int index)
        {
            if (index < 0 || (long)head == 0)
            {
                return(null);
            }

            Node *toFree = head->RemoveAt(index, (Node *)0, head);

            if ((long)toFree == 0)
            {
                return(null);
            }

            int result = toFree->GetPayload();

            if (toFree == head)
            {
                head = (Node *)toFree->GetLink();
            }
            else if (toFree == tail)
            {
                tail = (Node *)toFree->GetLink();
            }

            unmanagedMemory.FreeHGlobal((IntPtr)toFree);

            return(result);
        }
        unsafe int OptimizeDFS(int optimizedParentIndex, int nodeIndex, Node *optimizedNodes, Leaf *optimizedLeaves, ref int optimizedNodeCount, ref int optimizedLeafCount)
        {
            var node = nodes + nodeIndex;
            var optimizedNodeIndex = optimizedNodeCount++;
            var optimizedNode      = optimizedNodes + optimizedNodeIndex;

            *optimizedNode = *node;
            optimizedNode->Parent = optimizedParentIndex;
            var children = &optimizedNode->ChildA;

            for (int i = 0; i < node->ChildCount; ++i)
            {
                if (children[i] >= 0)
                {
                    children[i] = OptimizeDFS(optimizedNodeIndex, children[i], optimizedNodes, optimizedLeaves, ref optimizedNodeCount, ref optimizedLeafCount);
                }
                else
                {
                    var leafIndex          = Encode(children[i]);
                    var optimizedLeafIndex = optimizedLeafCount++;
                    var optimizedLeaf      = optimizedLeaves + optimizedLeafIndex;
                    optimizedLeaf->Id         = leaves[leafIndex].Id;
                    optimizedLeaf->NodeIndex  = optimizedNodeIndex;
                    optimizedLeaf->ChildIndex = i;
                    children[i] = Encode(optimizedLeafIndex);
                }
            }
            return(optimizedNodeIndex);
        }
        unsafe void ValidateStaging(Node *stagingNodes, int stagingNodeIndex, ref QuickList <int> subtreeNodePointers, ref QuickList <int> collectedSubtreeReferences, ref QuickList <int> internalReferences, out int foundSubtrees, out int foundLeafCount)
        {
            var stagingNode = stagingNodes + stagingNodeIndex;
            var children    = &stagingNode->ChildA;
            var leafCounts  = &stagingNode->LeafCountA;

            foundSubtrees = foundLeafCount = 0;
            for (int i = 0; i < stagingNode->ChildCount; ++i)
            {
                if (children[i] >= 0)
                {
                    int childFoundSubtrees, childFoundLeafCount;
                    if (internalReferences.Contains(children[i]))
                    {
                        throw new Exception("A child points to an internal node that was visited. Possible loop, or just general invalid.");
                    }
                    internalReferences.Add(children[i]);
                    ValidateStaging(stagingNodes, children[i], ref subtreeNodePointers, ref collectedSubtreeReferences, ref internalReferences, out childFoundSubtrees, out childFoundLeafCount);

                    if (childFoundLeafCount != leafCounts[i])
                    {
                        throw new Exception("Bad leaf count.");
                    }
                    foundSubtrees  += childFoundSubtrees;
                    foundLeafCount += childFoundLeafCount;
                }
                else
                {
                    var subtreeNodePointerIndex = Encode(children[i]);
                    var subtreeNodePointer      = subtreeNodePointers.Elements[subtreeNodePointerIndex];
                    //Rather than looking up the shuffled SweepSubtree for information, just go back to the source.
                    if (subtreeNodePointer >= 0)
                    {
                        var node           = nodes + subtreeNodePointer;
                        var totalLeafCount = 0;
                        for (int childIndex = 0; childIndex < node->ChildCount; ++childIndex)
                        {
                            totalLeafCount += (&node->LeafCountA)[childIndex];
                        }

                        if (leafCounts[i] != totalLeafCount)
                        {
                            throw new Exception("bad leaf count.");
                        }
                        foundLeafCount += totalLeafCount;
                    }
                    else
                    {
                        var leafIndex = Encode(subtreeNodePointer);
                        if (leafCounts[i] != 1)
                        {
                            throw new Exception("bad leaf count.");
                        }
                        foundLeafCount += 1;
                    }
                    ++foundSubtrees;
                    collectedSubtreeReferences.Add(subtreeNodePointer);
                }
            }
        }
Exemple #10
0
        /// <summary>
        /// Reads the next available node for reading into the specified byte array
        /// </summary>
        /// <param name="destination">Reference to the buffer</param>
        /// <param name="DontThrowException"> </param>
        /// <param name="timeout">The maximum number of milliseconds to wait for a node to become available for reading (default 10000ms)</param>
        /// <returns>positive: The number of bytes read, 0: read timeout occured, -1: No data continuity or Buffer overflow</returns>
        /// <remarks>The maximum number of bytes that can be read is the minimum of the length of <paramref name="destination"/> subtracted by <paramref name="startIndex"/> and <see cref="NodeBufferSize"/>.</remarks>
        public virtual int Read(byte[] destination, Boolean DontThrowException = false, int timeout = 10000)
        {
            Node *node = GetNodeForReading(timeout);

            if (node == null)
            {
                throw new Exception("Read Timeout");
                return(0); //timeout
            }

            int result = -1; //no data continuity

            Debug.Print("node->Index {1}, node->Counter {2}, _nextreadcounter {3}", 0, node->Index, node->ContinueCounter, _node_readcounter);
            if (node->ContinueCounter == _node_readcounter)
            {
                int amount = Math.Min(destination.Length, node->AmountWritten);
                result = amount;
                // Copy the data
                Marshal.Copy(new IntPtr(BufferStartPtr + node->Offset), destination, 0, amount);
                FreeNode(node);
                _node_readcounter++;
            }
            else
            {
                FreeNode(node);
                throw new Exception("No data continuity. Buffer overflow. Read faster from DAQBuffer");
            }
            return(result);
        }
Exemple #11
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);
        }
        unsafe void ReifyStagingNodes(int treeletRootIndex, Node *stagingNodes, ref QuickList <int> subtrees, ref QuickList <int> treeletInternalNodes, ref int nextInternalNodeIndexToUse, ref QuickList <int> spareNodes, out bool nodesInvalidated)
        {
            nodesInvalidated = false;
            //We take the staging node's child bounds, child indices, leaf counts, and child count.
            //The parent and index in parent of the treelet root CANNOT BE TOUCHED.
            //When running on multiple threads, another thread may modify the Parent and IndexInParent of the treelet root.
            var internalNode = nodes + treeletRootIndex;

            internalNode->ChildCount = stagingNodes->ChildCount;
            var bounds            = &internalNode->A;
            var children          = &internalNode->ChildA;
            var leafCounts        = &internalNode->LeafCountA;
            var stagingBounds     = &stagingNodes->A;
            var stagingChildren   = &stagingNodes->ChildA;
            var stagingLeafCounts = &stagingNodes->LeafCountA;

            for (int i = 0; i < internalNode->ChildCount; ++i)
            {
                bounds[i]     = stagingBounds[i];
                children[i]   = stagingChildren[i];
                leafCounts[i] = stagingLeafCounts[i];
            }

            ReifyChildren(treeletRootIndex, stagingNodes, ref subtrees, ref treeletInternalNodes, ref nextInternalNodeIndexToUse, ref spareNodes, out nodesInvalidated);
        }
Exemple #13
0
        /// <summary>
        /// Writes the structure to the next available node for writing
        /// </summary>
        /// <typeparam name="T">The structure type to be written</typeparam>
        /// <param name="source">The structure to be written</param>
        /// <param name="timeout">The maximum number of milliseconds to wait for a node to become available for writing (default 1000ms)</param>
        /// <returns>The number of bytes written - larger than 0 if successful</returns>
        /// <exception cref="ArgumentOutOfRangeException">If the size of the <typeparamref name="T"/> structure is larger than <see cref="NodeBufferSize"/>.</exception>
        public virtual int Write <T>(ref T source)
            where T : struct
        {
            int structSize = Marshal.SizeOf(typeof(T));

            if (structSize > NodeBufferSize)
            {
                throw new ArgumentOutOfRangeException("T", "The size of structure " + typeof(T).Name + " is larger than NodeBufferSize");
            }

            // Attempt to retrieve a node for writing
            Node *node = GetNodeForWriting();

            if (node == null)
            {
                return(0);
            }

            // Copy the data using the MemoryMappedViewAccessor
            base.Write <T>(ref source, node->Offset);
            node->AmountWritten = structSize;

            // Return the node for further writing
            PostNode(node);

            return(structSize);
        }
Exemple #14
0
        private static bool IsEar(Node *ear)
        {
            var a = ear->prev;
            var b = ear;
            var c = ear->next;

            if (Area(a, b, c) >= 0)
            {
                return(false);                    // reflex, can't be an ear
            }
            // now make sure we don't have other points inside the potential ear
            var p = ear->next->next;

            while (p != ear->prev)
            {
                if (PointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) &&
                    Area(p->prev, p, p->next) >= 0)
                {
                    return(false);
                }
                p = p->next;
            }

            return(true);
        }
        protected virtual void PostNode(Node *node)
        {
            // Set the write flag for this node (the node is reserved so no need for locks)
            node->DoneWrite = 1;

            // Move the write pointer as far forward as we can
            // always starting from WriteEnd to make all contiguous
            // completed nodes available for reading.
            for (; ;)
            {
                int blockIndex = _nodeHeader->WriteEnd;
                node = this[blockIndex];
                #pragma warning disable 0420 // ignore ref to volatile warning - Interlocked API
                if (Interlocked.CompareExchange(ref node->DoneWrite, 0, 1) != 1)
                {
                    // If we get here then another thread either another thread
                    // has already moved the write index or we have moved forward
                    // as far as we can
                    return;
                }

                // Move the pointer one forward
                Interlocked.CompareExchange(ref _nodeHeader->WriteEnd, node->Next, blockIndex);
                #pragma warning restore 0420

                // Signal the "data exists" event if read threads are waiting
                if (blockIndex == _nodeHeader->ReadStart)
                {
                    DataExists.Set();
                }
            }
        }
Exemple #16
0
        private Node *LinkedList(int start, int end, bool clockwise)
        {
            Node *last = null;

            if (clockwise == (SignedArea(start, end) > 0))
            {
                for (var i = start; i < end; i += _result.Dim)
                {
                    last = InsertNode(i, _result.Vertices[i], _result.Vertices[i + 1], last);
                }
            }
            else
            {
                for (var i = end - _result.Dim; i >= start; i -= _result.Dim)
                {
                    last = InsertNode(i, _result.Vertices[i], _result.Vertices[i + 1], last);
                }
            }

            if (last == null || !Equals(last, last->next))
            {
                return(last);
            }
            RemoveNode(last);

            last = last->next;

            return(last);
        }
Exemple #17
0
        private void SplitEarcut(Node *start, NativeList <int> triangles, float minX, float minY, float size)
        {
            var a = start;

            do
            {
                var b = a->next->next;
                while (b != a->prev)
                {
                    if (a->i != b->i && IsValidDiagonal(a, b))
                    {
                        // split the polygon in two by the diagonal
                        var c = SplitPolygon(a, b);

                        // filter co-linear points around the cuts
                        a = FilterPoints(a, a->next);
                        c = FilterPoints(c, c->next);

                        // run earcut on each half
                        EarcutLinked(a, triangles, minX, minY, size);
                        EarcutLinked(c, triangles, minX, minY, size);
                        return;
                    }

                    b = b->next;
                }

                a = a->next;
            } while (a != start);
        }
Exemple #18
0
        private Node *EliminateHoles(Node *outerNode)
        {
            int i;
            var len   = _result.Holes.Length;
            var queue = new NativeList <int>(len, Allocator.Temp);

            for (i = 0; i < len; i++)
            {
                var start = _result.Holes[i] * _result.Dim;
                var end   = i < len - 1 ? _result.Holes[i + 1] * _result.Dim : _result.Vertices.Length;

                var list = LinkedList(start, end, false);
                if (list == list->next)
                {
                    list->steiner = true;
                }
                queue.Add(GetLeftmost(list)->location);
            }

            queue.Sort(new Comparer(ref _heap));

            // process holes from left to right
            for (i = 0; i < queue.Length; i++)
            {
                var input = GetNodeAt(queue[i]);
                EliminateHole(input, outerNode);
                outerNode = FilterPoints(outerNode, outerNode->next);
            }

            return(outerNode);
        }
Exemple #19
0
        private Node *CureLocalIntersections(Node *start, NativeList <int> triangles)
        {
            var p = start;

            do
            {
                var a = p->prev;
                var b = p->next->next;

                if (!Equals(a, b) && Intersects(a, p, p->next, b) && LocallyInside(a, b) && LocallyInside(b, a))
                {
                    triangles.Add(a->i / _result.Dim);
                    triangles.Add(p->i / _result.Dim);
                    triangles.Add(b->i / _result.Dim);

                    // remove two nodes involved
                    RemoveNode(p);
                    RemoveNode(p->next);

                    p = start = b;
                }

                p = p->next;
            } while (p != start);

            return(p);
        }
Exemple #20
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="targetLeafSlotCount">The desired number of available leaf slots.</param>
        public void Resize(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 <Leaf> .GetLowestContainingElementCount(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 <Node> .GetLowestContainingElementCount(Math.Max(nodeCount, leafCapacityForTarget - 1));

            bool wasAllocated = Leaves.Allocated;

            Debug.Assert(Leaves.Allocated == Nodes.Allocated);
            if (leafCapacityForTarget != Leaves.Length)
            {
                Pool.SpecializeFor <Leaf>().Resize(ref Leaves, leafCapacityForTarget, leafCount);
                leaves = (Leaf *)Leaves.Memory;
            }
            if (nodeCapacityForTarget != Nodes.Length)
            {
                Pool.SpecializeFor <Node>().Resize(ref Nodes, nodeCapacityForTarget, nodeCount);
                //A node's RefineFlag must be 0, so just clear out the node set.
                //TODO: You could avoid the bulk of this by either a) getting rid of refine flags as a concept or b) using a separate array for the node metadata (a good idea anyway).
                Nodes.Clear(nodeCount, Nodes.Length - nodeCount);
                nodes = (Node *)Nodes.Memory;
            }
            if (!wasAllocated)
            {
                InitializeRoot();
            }
        }
Exemple #21
0
        public static bool Remove(UnsafeLinkedList *llist, ref Node *node)
        {
            UDebug.Assert(llist != null);

            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }

            Node *prev = null;
            Node *head = llist->_head;

            while (head != null)
            {
                if (head == node)
                {
                    llist->DeleteNode(head, prev);
                    node = null;

                    return(true);
                }

                // Advance to next node and remember the prev node.
                prev = head;
                head = head->_next;
            }

            return(false);
        }
        public virtual int Write(object source, int startIndex = 0, Type t = null, int timeout = 1000)
        {
            int structSize = Marshal.SizeOf(source.GetType());

            if (structSize > NodeBufferSize)
            {
                throw new ArgumentOutOfRangeException("T", "The size of structure " + source.GetType().Name + " is larger than NodeBufferSize");
            }

            // Attempt to retrieve a node for writing
            Node *node = GetNodeForWriting(timeout);

            if (node == null)
            {
                return(0);
            }

            // Copy the data using the MemoryMappedViewAccessor
            base.Write(source, node->Offset);
            node->AmountWritten = structSize;

            // Return the node for further writing
            PostNode(node);

            return(structSize);
        }
Exemple #23
0
        internal static bool RemoveSlow <T>(UnsafeLinkedList *llist, T item)
            where T : unmanaged
        {
            UDebug.Assert(llist != null);
            UDebug.Assert(typeof(T).TypeHandle.Value == llist->_typeHandle);

            Node *prev = null;
            Node *node = llist->_head;

            var eq = EqualityComparer <T> .Default;

            while (node != null)
            {
                if (eq.Equals(item, *GetItemFromNode <T>(node)))
                {
                    llist->DeleteNode(node, prev);
                    return(true);
                }

                // Advance to next node and remember the prev node.
                prev = node;
                node = node->_next;
            }

            return(false);
        }
Exemple #24
0
        public void ITprev()
        {
            var p = _prev(first, second);

            second = first;
            first  = p;
        }
Exemple #25
0
        unsafe static void BuildNode(Node *node, Point3 *points, int offset, int length, int depth)
        {
            // pick median
            int median = length >> 1;

            // pick splitting axis
            int axis = depth % 3;

            // split points by median
            SelectByAxis(median, points + offset, length, axis);

            // calc offsets
            var offsetL = offset;
            var offsetR = offset + median + 1;
            var lengthL = median;
            var lengthR = length - median - 1;
            var stepL   = lengthL > 0 ? 1 : 0;
            var stepR   = lengthR > 0 ? 1 + lengthL : 0;

            // make node
            node->point = offset + median;
            node->stepL = stepL;
            node->stepR = stepR;

            // build subtrees
            if (lengthL > 0)
            {
                BuildNode(node + stepL, points, offsetL, lengthL, depth + 1);
            }
            if (lengthR > 0)
            {
                BuildNode(node + stepR, points, offsetR, lengthR, depth + 1);
            }
        }
        protected virtual void ReturnNode(Node *node)
        {
            // Set the finished reading flag for this node (the node is reserved so no need for locks)
            node->DoneRead = 1;

            // Keep it clean and reset AmountWritten to prepare it for next Write
            node->AmountWritten = 0;

            // Move the read pointer forward as far as possible
            // always starting from ReadEnd to make all contiguous
            // read nodes available for writing.
            for (; ;)
            {
                int blockIndex = _nodeHeader->ReadEnd;
                node = this[blockIndex];
                #pragma warning disable 0420 // ignore ref to volatile warning - Interlocked API
                if (Interlocked.CompareExchange(ref node->DoneRead, 0, 1) != 1)
                {
                    // If we get here then another read thread has already moved the pointer
                    // or we have moved ReadEnd as far forward as we can
                    return;
                }

                // Move the pointer forward one node
                Interlocked.CompareExchange(ref _nodeHeader->ReadEnd, node->Next, blockIndex);
                #pragma warning restore 0420

                // If a writer thread is waiting on "node available" signal the event
                if (node->Prev == _nodeHeader->WriteStart)
                {
                    NodeAvailable.Set();
                }
            }
        }
Exemple #27
0
        /// <summary>
        /// Reserves a node for writing and then calls the provided <paramref name="writeFunc"/> to perform the write operation.
        /// </summary>
        /// <param name="writeFunc">A function to used to write to the node's buffer. The first parameter is a pointer to the node's buffer.
        /// The provided function should return the number of bytes written.</param>
        /// <returns>The number of bytes written</returns>
        public virtual int Write(Func <IntPtr, int> writeFunc)
        {
            // Grab a node for writing
            Node *node = GetNodeForWriting();

            if (node == null)
            {
                return(0);
            }

            int amount = 0;

            try
            {
                // Pass destination IntPtr to custom write function
                amount = writeFunc(new IntPtr(BufferStartPtr + node->Offset));
                node->AmountWritten = amount;
            }
            finally
            {
                // Writing is complete, make readable
                PostNode(node);
            }

            return(amount);
        }
        public virtual int Read(object destination, int startIndex = 0, Type t = null, int timeout = 1000)
        {
            int structSize = Marshal.SizeOf(t);

            if (structSize > NodeBufferSize)
            {
                throw new ArgumentOutOfRangeException("T", "The size of structure " + t.Name + " is larger than NodeBufferSize");
            }

            // Attempt to retrieve a node
            Node *node = GetNodeForReading(timeout);

            if (node == null && t != null)
            {
                destination = GetDefault(t);
                return(0);
            }

            // Copy the data using the MemoryMappedViewAccessor
            base.Read(destination, node->Offset);

            // Return the node for further writing
            ReturnNode(node);

            return(structSize);
        }
Exemple #29
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();
            }
        }
        unsafe void ValidateStaging(Node *stagingNodes, ref QuickList <int> subtreeNodePointers, int treeletParent, int treeletIndexInParent)
        {
            int             foundSubtrees, foundLeafCount;
            QuickList <int> collectedSubtreeReferences = new QuickList <int>(BufferPools <int> .Thread);
            QuickList <int> internalReferences         = new QuickList <int>(BufferPools <int> .Thread);

            internalReferences.Add(0);
            ValidateStaging(stagingNodes, 0, ref subtreeNodePointers, ref collectedSubtreeReferences, ref internalReferences, out foundSubtrees, out foundLeafCount);
            if (treeletParent < -1 || treeletParent >= nodeCount)
            {
                throw new Exception("Bad treelet parent.");
            }
            if (treeletIndexInParent < -1 || (treeletParent >= 0 && treeletIndexInParent >= nodes[treeletParent].ChildCount))
            {
                throw new Exception("Bad treelet index in parent.");
            }
            if (treeletParent >= 0 && (&nodes[treeletParent].LeafCountA)[treeletIndexInParent] != foundLeafCount)
            {
                throw new Exception("Bad leaf count.");
            }
            if (subtreeNodePointers.Count != foundSubtrees)
            {
                throw new Exception("Bad subtree found count.");
            }
            for (int i = 0; i < collectedSubtreeReferences.Count; ++i)
            {
                if (!subtreeNodePointers.Contains(collectedSubtreeReferences[i]) || !collectedSubtreeReferences.Contains(subtreeNodePointers[i]))
                {
                    throw new Exception("Bad subtree reference.");
                }
            }
            collectedSubtreeReferences.Dispose();
            internalReferences.Dispose();
        }
Exemple #31
0
 public Model()
 {
     _forward = (Node*)Memory.Alloc(sizeof(Node));
     _backward = (Node*)Memory.Alloc(sizeof(Node));
 }
 public override void BeginRender(Object sender, EventArgs e, Dictionary<String, UInt32> map)
 {
     head = *(Node**)map["watchedHead"];
 }