Skip to content

Commit 3fa0332

Browse files
committed
Add cacheEnabledState inheritance fix, UnmanagedAccessArray range indexer
1 parent 312707c commit 3fa0332

File tree

8 files changed

+617
-84
lines changed

8 files changed

+617
-84
lines changed

Medicine.Runtime/Utility/UnmanagedAccessArray.cs

Lines changed: 147 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ static readonly SharedStatic<TLayout> unmanagedLayoutStorage
2626
= SharedStatic<TLayout>.GetOrCreate<TLayout>();
2727

2828
UnsafeList<UnmanagedRef<TClass>> classRefArray;
29+
int rangeStart;
30+
int rangeLength;
2931

3032
[NativeDisableUnsafePtrRestriction]
3133
readonly TLayout* layoutInfo;
@@ -44,7 +46,7 @@ static readonly SharedStatic<int> s_staticSafetyId
4446
public readonly int Length
4547
{
4648
[MethodImpl(AggressiveInlining)]
47-
get => classRefArray.Length;
49+
get => rangeLength;
4850
}
4951

5052
public readonly bool IsCreated
@@ -56,6 +58,8 @@ public readonly bool IsCreated
5658
public void UpdateBuffer(UnsafeList<UnmanagedRef<TClass>> classRefArray)
5759
{
5860
this.classRefArray = classRefArray;
61+
rangeStart = 0;
62+
rangeLength = classRefArray.Length;
5963
#if ENABLE_UNITY_COLLECTIONS_CHECKS
6064
m_Length = classRefArray.Length;
6165
m_MinIndex = 0;
@@ -66,6 +70,8 @@ public void UpdateBuffer(UnsafeList<UnmanagedRef<TClass>> classRefArray)
6670
public UnmanagedAccessArray(UnsafeList<UnmanagedRef<TClass>> classRefArray)
6771
{
6872
this.classRefArray = classRefArray;
73+
rangeStart = 0;
74+
rangeLength = classRefArray.Length;
6975
layoutInfo = (TLayout*)unmanagedLayoutStorage.UnsafeDataPointer;
7076

7177
#if ENABLE_UNITY_COLLECTIONS_CHECKS
@@ -78,6 +84,31 @@ public UnmanagedAccessArray(UnsafeList<UnmanagedRef<TClass>> classRefArray)
7884
#endif
7985
}
8086

87+
UnmanagedAccessArray(
88+
UnsafeList<UnmanagedRef<TClass>> classRefArray,
89+
TLayout* layoutInfo,
90+
int rangeStart,
91+
int rangeLength
92+
#if ENABLE_UNITY_COLLECTIONS_CHECKS
93+
, int length,
94+
int minIndex,
95+
int maxIndex,
96+
AtomicSafetyHandle safety
97+
#endif
98+
)
99+
{
100+
this.classRefArray = classRefArray;
101+
this.layoutInfo = layoutInfo;
102+
this.rangeStart = rangeStart;
103+
this.rangeLength = rangeLength;
104+
#if ENABLE_UNITY_COLLECTIONS_CHECKS
105+
m_Length = length;
106+
m_MinIndex = minIndex;
107+
m_MaxIndex = maxIndex;
108+
m_Safety = safety;
109+
#endif
110+
}
111+
81112
public void Dispose()
82113
{
83114
#if ENABLE_UNITY_COLLECTIONS_CHECKS
@@ -98,11 +129,21 @@ public readonly JobHandle Dispose(JobHandle dependsOn)
98129
readonly void CheckIndexInRange(int index)
99130
{
100131
#if ENABLE_UNITY_COLLECTIONS_CHECKS
101-
if ((uint)index >= (uint)classRefArray.Length)
132+
if ((uint)index >= (uint)rangeLength)
102133
ThrowIndexOutOfRange(index);
103134
#endif
104135
}
105136

137+
[Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
138+
[MethodImpl(AggressiveInlining)]
139+
readonly void CheckAbsoluteIndexInRange(int index)
140+
{
141+
#if ENABLE_UNITY_COLLECTIONS_CHECKS
142+
if ((uint)index >= (uint)classRefArray.Length)
143+
ThrowAbsoluteIndexOutOfRange(index);
144+
#endif
145+
}
146+
106147
[Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
107148
[MethodImpl(AggressiveInlining)]
108149
readonly void CheckIndexInParallelWriteRange(int index)
@@ -125,6 +166,10 @@ readonly void CheckWriteAccess()
125166
#if ENABLE_UNITY_COLLECTIONS_CHECKS
126167
[MethodImpl(NoInlining)]
127168
readonly void ThrowIndexOutOfRange(int index)
169+
=> throw new IndexOutOfRangeException($"Index {index} is out of range of [0..{rangeLength - 1}].");
170+
171+
[MethodImpl(NoInlining)]
172+
readonly void ThrowAbsoluteIndexOutOfRange(int index)
128173
=> throw new IndexOutOfRangeException($"Index {index} is out of range of [0..{m_Length - 1}].");
129174

130175
[MethodImpl(NoInlining)]
@@ -160,21 +205,48 @@ public readonly TAccessRW this[int index]
160205
[MethodImpl(AggressiveInlining)]
161206
get
162207
{
163-
CheckWriteAccess();
164208
CheckIndexInRange(index);
165-
CheckIndexInParallelWriteRange(index);
209+
return AccessAt(rangeStart + index);
210+
}
211+
}
166212

167-
var access = new UntypedAccess(classRefArray[index], layoutInfo);
168-
return UnsafeUtility.As<UntypedAccess, TAccessRW>(ref access);
213+
public readonly UnmanagedAccessArray<TClass, TLayout, TAccessRW, TAccessRO> this[Range range]
214+
{
215+
[MethodImpl(AggressiveInlining)]
216+
get
217+
{
218+
var (offset, length) = range.GetOffsetAndLength(rangeLength);
219+
return new(
220+
classRefArray,
221+
layoutInfo,
222+
rangeStart + offset,
223+
length
224+
#if ENABLE_UNITY_COLLECTIONS_CHECKS
225+
, m_Length,
226+
m_MinIndex,
227+
m_MaxIndex,
228+
m_Safety
229+
#endif
230+
);
169231
}
170232
}
171233

234+
[MethodImpl(AggressiveInlining)]
235+
readonly TAccessRW AccessAt(int absoluteIndex)
236+
{
237+
CheckWriteAccess();
238+
CheckAbsoluteIndexInRange(absoluteIndex);
239+
CheckIndexInParallelWriteRange(absoluteIndex);
240+
var access = new UntypedAccess(classRefArray[absoluteIndex], layoutInfo);
241+
return UnsafeUtility.As<UntypedAccess, TAccessRW>(ref access);
242+
}
243+
172244
public readonly Enumerator GetEnumerator()
173245
=> new(this);
174246

175247
public readonly ReadOnly AsReadOnly()
176248
=> new(
177-
classRefArray, layoutInfo
249+
classRefArray, layoutInfo, rangeStart, rangeLength
178250
#if ENABLE_UNITY_COLLECTIONS_CHECKS
179251
, m_Safety
180252
#endif
@@ -185,21 +257,23 @@ public struct Enumerator
185257
{
186258
readonly UnmanagedAccessArray<TClass, TLayout, TAccessRW, TAccessRO> array;
187259
int index;
260+
readonly int endExclusive;
188261

189262
public Enumerator(UnmanagedAccessArray<TClass, TLayout, TAccessRW, TAccessRO> array)
190263
{
191264
this.array = array;
192-
index = -1;
265+
index = array.rangeStart - 1;
266+
endExclusive = array.rangeStart + array.rangeLength;
193267

194268
array.CheckWriteAccess();
195269

196270
#if MODULE_BURST && UNITY_BURST_EXPERIMENTAL_PREFETCH_INTRINSIC && !MEDICINE_DISABLE_UNMANAGEDACCESSARRAY_PREFETCH
197-
var len = array.classRefArray.Length;
271+
var len = array.rangeLength;
198272
if (len > 0)
199273
{
200274
int count = len < PrefetchDistance ? len : PrefetchDistance;
201275
for (int i = 0; i < count; i++)
202-
Common.Prefetch((void*)array.classRefArray.Ptr[i].Ptr, Common.ReadWrite.Write);
276+
Common.Prefetch((void*)array.classRefArray.Ptr[array.rangeStart + i].Ptr, Common.ReadWrite.Write);
203277
}
204278
#endif
205279
}
@@ -209,12 +283,12 @@ public bool MoveNext()
209283
{
210284
array.CheckWriteAccess();
211285

212-
if (++index >= array.classRefArray.Length)
286+
if (++index >= endExclusive)
213287
return false;
214288

215289
#if MODULE_BURST && UNITY_BURST_EXPERIMENTAL_PREFETCH_INTRINSIC && !MEDICINE_DISABLE_UNMANAGEDACCESSARRAY_PREFETCH
216290
int prefetchOffset = index + PrefetchDistance;
217-
if ((uint)prefetchOffset < (uint)array.classRefArray.Length)
291+
if ((uint)prefetchOffset < (uint)endExclusive)
218292
Common.Prefetch((void*)array.classRefArray.Ptr[prefetchOffset].Ptr, Common.ReadWrite.Write);
219293
#endif
220294

@@ -224,7 +298,7 @@ public bool MoveNext()
224298
public TAccessRW Current
225299
{
226300
[MethodImpl(AggressiveInlining)]
227-
get => array[index];
301+
get => array.AccessAt(index);
228302
}
229303
}
230304

@@ -233,6 +307,8 @@ public TAccessRW Current
233307
public readonly struct ReadOnly
234308
{
235309
readonly UnsafeList<UnmanagedRef<TClass>> classRefArray;
310+
readonly int rangeStart;
311+
readonly int rangeLength;
236312

237313
[NativeDisableUnsafePtrRestriction]
238314
readonly TLayout* layoutInfo;
@@ -244,7 +320,7 @@ public readonly struct ReadOnly
244320
public int Length
245321
{
246322
[MethodImpl(AggressiveInlining)]
247-
get => classRefArray.Length;
323+
get => rangeLength;
248324
}
249325

250326
public bool IsCreated
@@ -254,14 +330,19 @@ public bool IsCreated
254330
}
255331

256332
public ReadOnly(
257-
UnsafeList<UnmanagedRef<TClass>> classRefArray, TLayout* layoutInfo
333+
UnsafeList<UnmanagedRef<TClass>> classRefArray,
334+
TLayout* layoutInfo,
335+
int rangeStart,
336+
int rangeLength
258337
#if ENABLE_UNITY_COLLECTIONS_CHECKS
259338
, AtomicSafetyHandle safety
260339
#endif
261340
)
262341
{
263342
this.classRefArray = classRefArray;
264343
this.layoutInfo = layoutInfo;
344+
this.rangeStart = rangeStart;
345+
this.rangeLength = rangeLength;
265346
#if ENABLE_UNITY_COLLECTIONS_CHECKS
266347
m_Safety = safety;
267348
#endif
@@ -272,11 +353,21 @@ public ReadOnly(
272353
void CheckIndexInRange(int index)
273354
{
274355
#if ENABLE_UNITY_COLLECTIONS_CHECKS
275-
if ((uint)index >= (uint)classRefArray.Length)
356+
if ((uint)index >= (uint)rangeLength)
276357
ThrowIndexOutOfRange(index);
277358
#endif
278359
}
279360

361+
[Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
362+
[MethodImpl(AggressiveInlining)]
363+
void CheckAbsoluteIndexInRange(int index)
364+
{
365+
#if ENABLE_UNITY_COLLECTIONS_CHECKS
366+
if ((uint)index >= (uint)classRefArray.Length)
367+
ThrowAbsoluteIndexOutOfRange(index);
368+
#endif
369+
}
370+
280371
[Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
281372
[MethodImpl(AggressiveInlining)]
282373
void CheckReadAccess()
@@ -289,6 +380,10 @@ void CheckReadAccess()
289380
#if ENABLE_UNITY_COLLECTIONS_CHECKS
290381
[MethodImpl(NoInlining)]
291382
void ThrowIndexOutOfRange(int index)
383+
=> throw new IndexOutOfRangeException($"Index {index} is out of range of [0..{rangeLength - 1}].");
384+
385+
[MethodImpl(NoInlining)]
386+
void ThrowAbsoluteIndexOutOfRange(int index)
292387
=> throw new IndexOutOfRangeException($"Index {index} is out of range of [0..{classRefArray.Length - 1}].");
293388
#endif
294389

@@ -297,14 +392,38 @@ public TAccessRO this[int index]
297392
[MethodImpl(AggressiveInlining)]
298393
get
299394
{
300-
CheckReadAccess();
301395
CheckIndexInRange(index);
396+
return AccessAt(rangeStart + index);
397+
}
398+
}
302399

303-
var access = new UntypedAccess(classRefArray[index], layoutInfo);
304-
return UnsafeUtility.As<UntypedAccess, TAccessRO>(ref access);
400+
public ReadOnly this[Range range]
401+
{
402+
[MethodImpl(AggressiveInlining)]
403+
get
404+
{
405+
var (offset, length) = range.GetOffsetAndLength(rangeLength);
406+
return new(
407+
classRefArray,
408+
layoutInfo,
409+
rangeStart + offset,
410+
length
411+
#if ENABLE_UNITY_COLLECTIONS_CHECKS
412+
, m_Safety
413+
#endif
414+
);
305415
}
306416
}
307417

418+
[MethodImpl(AggressiveInlining)]
419+
TAccessRO AccessAt(int absoluteIndex)
420+
{
421+
CheckReadAccess();
422+
CheckAbsoluteIndexInRange(absoluteIndex);
423+
var access = new UntypedAccess(classRefArray[absoluteIndex], layoutInfo);
424+
return UnsafeUtility.As<UntypedAccess, TAccessRO>(ref access);
425+
}
426+
308427
public Enumerator GetEnumerator()
309428
=> new(this);
310429

@@ -314,19 +433,21 @@ public struct Enumerator
314433
{
315434
readonly ReadOnly array;
316435
int index;
436+
readonly int endExclusive;
317437

318438
public Enumerator(in ReadOnly array)
319439
{
320440
this.array = array;
321-
index = -1;
441+
index = array.rangeStart - 1;
442+
endExclusive = array.rangeStart + array.rangeLength;
322443

323444
#if MODULE_BURST && UNITY_BURST_EXPERIMENTAL_PREFETCH_INTRINSIC && !MEDICINE_DISABLE_UNMANAGEDACCESSARRAY_PREFETCH
324-
var len = array.Length;
445+
var len = array.rangeLength;
325446
if (len > 0)
326447
{
327448
int count = len < PrefetchDistance ? len : PrefetchDistance;
328449
for (int i = 0; i < count; i++)
329-
Common.Prefetch((void*)array.classRefArray.Ptr[i].Ptr, Common.ReadWrite.Read);
450+
Common.Prefetch((void*)array.classRefArray.Ptr[array.rangeStart + i].Ptr, Common.ReadWrite.Read);
330451
}
331452
#endif
332453
}
@@ -336,12 +457,12 @@ public bool MoveNext()
336457
{
337458
array.CheckReadAccess();
338459

339-
if (++index >= array.classRefArray.Length)
460+
if (++index >= endExclusive)
340461
return false;
341462

342463
#if MODULE_BURST && UNITY_BURST_EXPERIMENTAL_PREFETCH_INTRINSIC && !MEDICINE_DISABLE_UNMANAGEDACCESSARRAY_PREFETCH
343464
int prefetchOffset = index + PrefetchDistance;
344-
if ((uint)prefetchOffset < (uint)array.classRefArray.Length)
465+
if ((uint)prefetchOffset < (uint)endExclusive)
345466
Common.Prefetch((void*)array.classRefArray.Ptr[prefetchOffset].Ptr, Common.ReadWrite.Read);
346467
#endif
347468

@@ -351,9 +472,9 @@ public bool MoveNext()
351472
public TAccessRO Current
352473
{
353474
[MethodImpl(AggressiveInlining)]
354-
get => array[index];
475+
get => array.AccessAt(index);
355476
}
356477
}
357478
}
358479
}
359-
}
480+
}

Medicine.SourceGenerator.Tests~/Program.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
Med032Test.Case,
4141
InjectSourceGeneratorTest.Case,
4242
TrackSourceGeneratorTest.Case,
43+
TrackSourceGeneratorTest.CacheEnabledStateInheritanceCase,
4344
SingletonSourceGeneratorTest.Case,
4445
UnionSourceGeneratorTest.Case,
4546
UnionSourceGeneratorTest.NoDerivedHeaderCase,
@@ -50,6 +51,9 @@
5051
UnionNestedSourceGeneratorTest.Case,
5152
UnionNestedSourceGeneratorTest.HeaderFieldForwardingCase,
5253
UnmanagedAccessSourceGeneratorTest.Case,
54+
UnmanagedAccessSourceGeneratorTest.RangeIndexerCase,
55+
UnmanagedAccessSourceGeneratorTest.CacheEnabledStateInheritanceCase,
56+
UnmanagedAccessSourceGeneratorTest.DirectIInstanceIndexCase,
5357
WrapValueEnumerableSourceGeneratorTest.Case,
5458
ConstantsSourceGeneratorTest.Case,
5559
ConstantsMissingInputSourceGeneratorTest.Case,

0 commit comments

Comments
 (0)