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