gpt4 book ai didi

How can I write an enumerator for nested unmanaged enumerables?(如何为嵌套的非托管可枚举数编写枚举器?)

转载 作者:bug小助手 更新时间:2023-10-26 20:08:39 31 4
gpt4 key购买 nike



I've written enumerators based on the existing NativeHashMap.Enumerator and UnsafeHashMap.Enumerator structs that work in burst, but I am running into trouble when I try to combine enumerators for nested unmanaged structs. Specifically I am running into a problem where the first level works, but the second level only returns the first element of the set because the enumerator it depends on is getting corrupted or reset.

我已经基于现有的NativeHashMap.Enumerator和UnSafeHashMap.Enumerator结构编写了枚举数,它们以猝发方式工作,但在尝试为嵌套的非托管结构组合枚举数时遇到了麻烦。具体地说,我遇到了一个问题,其中第一级可以工作,但第二级只返回集合中的第一个元素,因为它所依赖的枚举数已损坏或重置。


In my example I have three structs: Parent, Child, and GrandChild. Parent contains a NativeHashMap of Child, and Child contains an UnsafeHashMap of GrandChild. I can iterate over a Parent's Chilren using TestEnumerator.NativeMap. I can also iterate over a Child's GrandChildren using TestEnumerator.UnsafeMap. My problem is that when I try to combine these two enumerators into TestEnumerator.AllGrandChildren, the UnsafeMap Enumerator gets corrupted each time that AllGrandChildren.MoveNext() is called, and only the first GrandChild from every Child is returned.

在我的示例中,我有三个结构:父结构、子结构和孙子结构。父项包含子项的NativeHashMap,而子项包含孙项的UnSafeHashMap。我可以使用TestEnumerator.NativeMap迭代父母的孩子。我还可以使用TestEnumerator.UnSafeMap遍历儿童的孙子对象。我的问题是,当我尝试将这两个枚举数组合到TestEnumerator.AllGrandChildren中时,每次调用AllGrandChildren.MoveNext()时,UnSafeMap枚举器都会损坏,并且只返回每个子对象中的第一个孙子对象。


using UnityEngine;
using Unity.Collections;
using System.Collections.Generic;
using System;
using Unity.Collections.LowLevel.Unsafe;
using System.Collections;

public class NestedEnumeratorTest : MonoBehaviour
{
void Start()
{
{
TestChild child = new TestChild(Allocator.Temp);

for (int i = 0; i < 100; i++)
{
child.Add(new TestGrandChild(-1, i));
}

int count = 0;
foreach (TestGrandChild grandchild in child.GrandChildren)
{
count++;
}
Debug.Log("Number of grandchildren in child: " + count); // Logs 100
}

{
TestParent parent = new TestParent(Allocator.Temp);

for (int i = 0; i < 10; i++)
{
TestChild child = new TestChild(Allocator.Temp);

for (int j = 0; j < 10; j++)
{
child.Add(new TestGrandChild(i, j));
}

parent.Add(child);
}

int count = 0;
foreach (TestGrandChild grandchild in parent.AllGrandChildren)
{
count++;
}
Debug.Log("Number of grandchildren in parent: " + count); // Logs 10
}
}
}

public struct TestEmumerable
{
public struct AllGrandChildren : IEnumerable<TestGrandChild>
{
private NativeHashMap<int, TestChild>.Enumerator enumerator;

public readonly TestEmumerator.AllGrandChildren Enumerator => new(enumerator);

public AllGrandChildren(NativeHashMap<int, TestChild>.Enumerator enumerator)
{
this.enumerator = enumerator;
}

public IEnumerator<TestGrandChild> GetEnumerator()
{
return Enumerator;
}

IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}

public struct NativeMap<Key, Value> : IEnumerable<Value>
where Key : unmanaged, IEquatable<Key>
where Value : unmanaged
{
private NativeHashMap<Key, Value>.Enumerator enumerator;

public readonly TestEmumerator.NativeMap<Key, Value> Enumerator => new(enumerator);

public NativeMap(NativeHashMap<Key, Value>.Enumerator enumerator)
{
this.enumerator = enumerator;
}

public IEnumerator<Value> GetEnumerator()
{
return Enumerator;
}

IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}

public struct UnsafeMap<Key, Value> : IEnumerable<Value>
where Key : unmanaged, IEquatable<Key>
where Value : unmanaged
{
private UnsafeHashMap<Key, Value>.Enumerator enumerator;

public readonly TestEmumerator.UnsafeMap<Key, Value> Enumerator => new(enumerator);

public UnsafeMap(UnsafeHashMap<Key, Value>.Enumerator enumerator)
{
this.enumerator = enumerator;
}

public IEnumerator<Value> GetEnumerator()
{
return Enumerator;
}

IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
}

public struct TestEmumerator
{
public struct AllGrandChildren : IEnumerator<TestGrandChild>
{
private NativeMap<int, TestChild> children; // Why can't I use a custom type here?
private UnsafeMap<int, TestGrandChild> grandchildren;
private NativeReference<bool> started;

public AllGrandChildren(NativeHashMap<int, TestChild>.Enumerator children)
{
this.children = new(children);
grandchildren = new();
started = new(false, Allocator.Temp);
}

public TestGrandChild Current => grandchildren.Current;

object IEnumerator.Current => Current;

public bool MoveNext()
{
bool moveNext;

if (started.Value)
{
moveNext = grandchildren.MoveNext();
}
else
{
started.Value = true;
moveNext = false;
}

while (!moveNext && children.MoveNext())
{
grandchildren = children.Current.GrandChildren.Enumerator;
moveNext = grandchildren.MoveNext();
}

return moveNext;
}

public void Reset()
{
if (started.Value)
{
started.Value = false;
}

children.Reset();
}

public void Dispose()
{

}
}

public struct NativeMap<Key, Value> : IEnumerator<Value>, IDisposable
where Key : unmanaged, IEquatable<Key>
where Value : unmanaged
{
private NativeHashMap<Key, Value>.Enumerator enumerator;

public NativeMap(NativeHashMap<Key, Value>.Enumerator enumerator)
{
this.enumerator = enumerator;
}

public Value Current => enumerator.Current.Value;

object IEnumerator.Current => Current;

public void Dispose()
{

}

public bool MoveNext()
{
return enumerator.MoveNext();
}

public void Reset()
{
enumerator.Reset();
}
}

public struct UnsafeMap<Key, Value> : IEnumerator<Value>, IDisposable
where Key : unmanaged, IEquatable<Key>
where Value : unmanaged
{
private UnsafeHashMap<Key, Value>.Enumerator enumerator;

public UnsafeMap(UnsafeHashMap<Key, Value>.Enumerator enumerator)
{
this.enumerator = enumerator;
}

public unsafe Value Current => enumerator.Current.Value;

object IEnumerator.Current => Current;

public void Dispose()
{

}

public bool MoveNext()
{
return enumerator.MoveNext();
}

public void Reset()
{
enumerator.Reset();
}
}
}

public struct TestParent
{
NativeHashMap<int, TestChild> children;
public TestEmumerable.NativeMap<int, TestChild> Children => new(children.GetEnumerator());
public TestEmumerable.AllGrandChildren AllGrandChildren => new(children.GetEnumerator());

public TestParent(Allocator allocator)
{
children = new(10, allocator);
}

public void Add(TestChild child)
{
children[children.Count] = child;
}
}

public struct TestChild
{
private UnsafeHashMap<int, TestGrandChild> grandchildren;
public TestEmumerable.UnsafeMap<int, TestGrandChild> GrandChildren => new(grandchildren.GetEnumerator());

public TestChild(Allocator allocator)
{
grandchildren = new(10, allocator);
}

public void Add(TestGrandChild grandchild)
{
grandchildren[grandchildren.Count] = grandchild;
}
}

public struct TestGrandChild
{
int parent;
int child;
public TestGrandChild(int parent, int child)
{
this.parent = parent;
this.child = child;
}
}

Edit:
I solved my problem, but I don't know why my solution works. In TestEmumerator.AllGrandChildren, If I use NativeHashMap.Enumerator instead of my custom TestEnumerator.NativeMap type for the children property, everything starts working. Can someone help explain why this is?

编辑:我解决了我的问题,但我不知道我的解决方案为什么有效。在TestEmumerator.AllGrandChildren中,如果我使用NativeHashMap.Enumerator而不是我的定制TestEnumerator.NativeMap类型作为Child属性,则一切都将开始工作。有人能解释一下为什么会这样吗?


更多回答
优秀答案推荐
更多回答

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com