/// <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); }
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++; }
/// <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); }
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); } }
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); } } }
/// <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); }
/// <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); }
/// <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); }
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(); } } }
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); }
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); }
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); }
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); }
/// <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(); } }
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); }
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); }
public void ITprev() { var p = _prev(first, second); second = first; first = p; }
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(); } } }
/// <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); }
/// <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(); }
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"]; }