A game about forced loneliness, made by TACStudios
1using NUnit.Framework;
2using System.Collections.Generic;
3using Unity.Jobs;
4using Unity.Burst;
5using Unity.Collections;
6using Unity.Collections.Tests;
7using Assert = FastAssert;
8using System;
9
10internal class NativeQueueTests_InJobs : CollectionsTestCommonBase
11{
12 struct NestedContainerJob : IJob
13 {
14 public NativeQueue<NativeQueue<int>> nestedContainer;
15
16 public void Execute()
17 {
18 nestedContainer.Clear();
19 }
20 }
21
22 [Test]
23 [TestRequiresCollectionChecks]
24 public void NativeQueue_NestedJob_Error()
25 {
26 var container = new NativeQueue<NativeQueue<int>>(CommonRwdAllocator.Handle);
27
28 var nestedJob = new NestedContainerJob
29 {
30 nestedContainer = container
31 };
32
33 JobHandle job = default;
34 Assert.Throws<System.InvalidOperationException>(() => { job = nestedJob.Schedule(); });
35 job.Complete();
36
37 container.Dispose();
38 }
39
40 [BurstCompile(CompileSynchronously = true)]
41 struct ConcurrentEnqueue : IJobParallelFor
42 {
43 public NativeQueue<int>.ParallelWriter queue;
44
45 [NativeDisableParallelForRestriction]
46 public NativeArray<int> result;
47
48 public int StartIndex;
49
50 public void Execute(int index)
51 {
52 index += StartIndex;
53 result[index] = 1;
54 queue.Enqueue(index);
55 }
56 }
57
58 [Test]
59 public void Enqueue()
60 {
61 const int queueSize = 100 * 1024;
62 var queue = new NativeQueue<int>(CommonRwdAllocator.Handle);
63 var writeStatus = CollectionHelper.CreateNativeArray<int>(queueSize, CommonRwdAllocator.Handle);
64
65 var enqueueJob = new ConcurrentEnqueue()
66 {
67 queue = queue.AsParallelWriter(),
68 result = writeStatus,
69 StartIndex = 0,
70 };
71
72 var enqueue = enqueueJob.Schedule(queueSize, 1);
73 enqueue.Complete();
74
75 Assert.AreEqual(queueSize, queue.Count, "Job enqueued the wrong number of values");
76 var allValues = new NativeParallelHashSet<int>(queueSize, Allocator.Persistent);
77 for (int i = 0; i < queueSize; ++i)
78 {
79 Assert.AreEqual(1, writeStatus[i], "Job failed to enqueue value");
80 int enqueued = queue.Dequeue();
81 Assert.IsTrue(enqueued >= 0 && enqueued < queueSize, "Job enqueued invalid value");
82 Assert.IsTrue(allValues.Add(enqueued), "Job enqueued same value multiple times");
83 }
84
85 var disposeJob = queue.Dispose(enqueue);
86 disposeJob.Complete();
87
88 writeStatus.Dispose();
89 allValues.Dispose();
90 }
91
92 [BurstCompile(CompileSynchronously = true)]
93 struct EnqueueDequeueJob : IJob
94 {
95 public NativeQueue<int> queue;
96 [ReadOnly] public NativeArray<int> arr;
97 public int val;
98
99 public void Execute()
100 {
101 for (int i = 0; i < 10000; ++i)
102 {
103 queue.Enqueue(0);
104 val += arr[queue.Dequeue()];
105 }
106 }
107 }
108
109 [Test]
110 public void EnqueueDequeueMultipleQueuesInMultipleJobs()
111 {
112 var handles = new NativeArray<JobHandle>(4, Allocator.Temp);
113 for (int i = 0; i < 10; ++i)
114 {
115 var q1 = new NativeQueue<int>(CommonRwdAllocator.Handle);
116 var q2 = new NativeQueue<int>(CommonRwdAllocator.Handle);
117 var q3 = new NativeQueue<int>(CommonRwdAllocator.Handle);
118 var q4 = new NativeQueue<int>(CommonRwdAllocator.Handle);
119 var rangeCheck = CollectionHelper.CreateNativeArray<int>(1, CommonRwdAllocator.Handle);
120 var j1 = new EnqueueDequeueJob {queue = q1, arr = rangeCheck, val = 0};
121 var j2 = new EnqueueDequeueJob {queue = q2, arr = rangeCheck, val = 0};
122 var j3 = new EnqueueDequeueJob {queue = q3, arr = rangeCheck, val = 0};
123 var j4 = new EnqueueDequeueJob {queue = q4, arr = rangeCheck, val = 0};
124 handles[0] = j1.Schedule();
125 handles[1] = j2.Schedule();
126 handles[2] = j3.Schedule();
127 handles[3] = j4.Schedule();
128 JobHandle.ScheduleBatchedJobs();
129
130 JobHandle.CombineDependencies(handles).Complete();
131
132 q1.Dispose();
133 q2.Dispose();
134 q3.Dispose();
135 q4.Dispose();
136 rangeCheck.Dispose();
137 }
138 handles.Dispose();
139 }
140
141 struct EnqueueJob : IJobParallelFor
142 {
143 public NativeQueue<int>.ParallelWriter Queue;
144 public void Execute(int index)
145 {
146 Queue.Enqueue(index);
147 }
148 }
149
150 [Test]
151 public void ToArray_WorksFromJobs()
152 {
153 using (var queue = new NativeQueue<int>(CommonRwdAllocator.Handle))
154 {
155 new EnqueueJob
156 {
157 Queue = queue.AsParallelWriter()
158 }.Schedule(100, 10).Complete();
159 Assert.AreEqual(100, queue.Count);
160 using (var arr = queue.ToArray(Allocator.Temp))
161 {
162 Assert.AreEqual(100, arr.Length);
163 arr.Sort();
164 for (int i = 0; i < arr.Length; i++)
165 Assert.AreEqual(i, arr[i]);
166 }
167 }
168 }
169
170 [Test]
171 public void NativeQueue_ParallelWriter()
172 {
173 const int queueSize = 100 * 1024;
174 var queue = new NativeQueue<int>(CommonRwdAllocator.Handle);
175 var writeStatus = CollectionHelper.CreateNativeArray<int>(queueSize, CommonRwdAllocator.Handle);
176
177 var jobHandle = new ConcurrentEnqueue()
178 {
179 queue = queue.AsParallelWriter(),
180 result = writeStatus,
181 StartIndex = 0,
182
183 }.Schedule(queueSize / 2, 1);
184
185 jobHandle = new ConcurrentEnqueue()
186 {
187 queue = queue.AsParallelWriter(),
188 result = writeStatus,
189 StartIndex = queueSize / 2,
190
191 }.Schedule(queueSize / 2, 1, jobHandle);
192
193 jobHandle.Complete();
194
195 Assert.AreEqual(queueSize, queue.Count, "Job enqueued the wrong number of values");
196 var allValues = new NativeParallelHashSet<int>(queueSize, Allocator.Persistent);
197 for (int i = 0; i < queueSize; ++i)
198 {
199 Assert.AreEqual(1, writeStatus[i], "Job failed to enqueue value");
200 int enqueued = queue.Dequeue();
201 Assert.IsTrue(enqueued >= 0 && enqueued < queueSize, "Job enqueued invalid value");
202 Assert.IsTrue(allValues.Add(enqueued), "Job enqueued same value multiple times");
203 }
204
205 var disposeJob = queue.Dispose(jobHandle);
206 disposeJob.Complete();
207
208 writeStatus.Dispose();
209 allValues.Dispose();
210 }
211}