Search Unity

NativeQueue Count wrongly asks for previous job completion but TryDequeue doesn't.

Discussion in 'Data Oriented Technology Stack' started by iam2bam, Dec 19, 2018.

  1. iam2bam


    Mar 9, 2016
    EDIT: This was related to a system not getting input dependencies because it was not processing any of the same component types as the other. Read more here.
    It was a freak race condition that allowed writing but not reading... Couldn't reproduce once fixed.

    I guess it's maybe because Count calls AtomicSafetyHandle.CheckReadAndThrow and TryDequeue just AtomicSafetyHandle.CheckWriteAndThrow.

    The weird thing is they DO complete. I've used
    1. A ComponentSystem
    2. A JobComponentSystem, with inputDeps.Complete()
    3. A previous BarrierSystem
    It doesn't matter it always has this trace:
    Code (CSharp):
    1. InvalidOperationException: The previously scheduled job Sys_EventQueue_Raise:Job writes to the NativeArray Job.Data._entsMT. You must call JobHandle.Complete() on the job Sys_EventQueue_Raise:Job, before you can read from the NativeArray safely.
    2. Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckReadAndThrowNoEarlyOut (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle handle) <0x30f963e0 + 0x00052> in <2f14d49edc704940aee557642343f344>:0
    3. Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckReadAndThrow (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle handle) (at C:/buildslave/unity/build/Runtime/Export/AtomicSafetyHandle.bindings.cs:143)
    4. Unity.Collections.NativeQueue`1[T].get_Count () (at C:/Users/dosbam/AppData/Local/Unity/cache/packages/
    The offending job from Sys_EventQueue_Raise is managed by a JobComponentSystem, can't do a Complete manually besides inputDeps.

    Dependencies seem OK (QueueSystem runs the offended job with _entsMT) :
    Code (CSharp):
    1.     [UpdateAfter(typeof(Sys_EventQueue_Raise))]
    2.     [UpdateBefore(typeof(QueueSystem))]
    3.     public class Sys_EventQueue_RaiseBarrier : BarrierSystem { }
    I don't actually need a Count, just a safe way if it has anything pending. Could try-catch a Peek() but also has a CheckReadAndThrow, also why should I have to...
    I can't "un-dequeue" after a TryDequeue check.

    if(TryGet) do { } while(TryGet)
    idiom from all NativeContainers is irritating...

    Versions from package manager:
    • com.unity.entities@0.0.12-preview.21
    • com.unity.collections@0.0.9-preview.10

    EDIT: Workaround/use case, if anyone is interested...
    Code (CSharp):
    1. //Batch-create entities for each event.
    2. if(_queueEvents.TryDequeue(out ev)) {
    3.     //***NOTICE***: Count+1 because we just dequeued one.
    4.     _entities = new NativeArray<Entity>(_queueEvents.Count+1, Allocator.TempJob);
    5.     _emgr.CreateEntity(_archetype, _entities);
    7.     var eventByEntArray = GetComponentDataFromEntity<Dat_EventWithSource>();
    8.     int index = 0;
    9.     do {
    10.         eventByEntArray[_entities[index++]] = ev;
    11.     } while(_queueEvents.TryDequeue(out ev));
    12. }
    Last edited: Dec 21, 2018