Search Unity

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

Discussion in 'Entity Component System' started by iam2bam, Dec 19, 2018.

  1. iam2bam

    iam2bam

    Joined:
    Mar 9, 2016
    Posts:
    36
    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/packages.unity.com/com.unity.collections@0.0.9-preview.10/Unity.Collections/NativeQueue.cs:226)
    5.  
    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.

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


    Versions from package manager:
    • com.unity.jobs@0.0.7-preview.5
    • 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);
    6.  
    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