Search Unity

Issue allocating NativeQueue when NativeList are scheduled to dispose

Discussion in 'Data Oriented Technology Stack' started by cjddmut, Oct 2, 2019.

  1. cjddmut

    cjddmut

    Joined:
    Nov 19, 2012
    Posts:
    120
    I noticed recently that the native containers have received schedulable Dispose function (which is great!) so I've been using them but noticed that every once in a while I'll get an error when trying to use a newly allocated container.

    Below is a constructed example that almost immediately hits the error (on my computer at least).

    Code (CSharp):
    1. using Unity.Collections;
    2. using Unity.Jobs;
    3. using UnityEngine;
    4.  
    5. public class TestParallelWriterDealloc : MonoBehaviour
    6. {
    7.     private struct TestJob : IJobParallelFor
    8.     {
    9.         public NativeQueue<int>.ParallelWriter writer;
    10.        
    11.         public void Execute(int index)
    12.         {
    13.             writer.Enqueue(index);
    14.         }
    15.     }
    16.  
    17.     private struct ListJob : IJob
    18.     {
    19.         public NativeList<int> list;
    20.  
    21.         public void Execute()
    22.         {
    23.             for (int i = 0; i < 100; i++)
    24.             {
    25.                 list.Add(i);;
    26.             }
    27.         }
    28.     }
    29.    
    30.     private void Update()
    31.     {
    32.         JobHandle handle = default;
    33.        
    34.         NativeList<int> list1 = new NativeList<int>(100, Allocator.TempJob);
    35.            
    36.         ListJob listJob1 = new ListJob();
    37.         listJob1.list = list1;
    38.  
    39.         JobHandle listHandle1 = listJob1.Schedule(handle);
    40.  
    41.         NativeList<int> list2 = new NativeList<int>(100, Allocator.TempJob);
    42.  
    43.         ListJob listJob2 = new ListJob();
    44.         listJob2.list = list2;
    45.  
    46.         JobHandle listHandle2 = listJob2.Schedule(handle);
    47.  
    48.         handle = JobHandle.CombineDependencies(listHandle1, listHandle2);
    49.         handle = JobHandle.CombineDependencies(list1.Dispose(handle), list2.Dispose(handle));
    50.        
    51.         // Forcing a complete here will fix the issue
    52.         //handle.Complete();
    53.            
    54.         NativeQueue<int> queue = new NativeQueue<int>(Allocator.TempJob);
    55.            
    56.         TestJob job = new TestJob();
    57.         job.writer = queue.AsParallelWriter();
    58.        
    59.         // The job fails with the following exception
    60.         // InvalidOperationException: The NativeContainer TestJob.writer has been deallocated. All containers must be valid when scheduling a job.
    61.         handle = job.Schedule(43, 16, handle);
    62.         handle = queue.Dispose(handle);
    63.        
    64.         handle.Complete();
    65.     }
    66. }
    This is close to what I'm doing in the actual code. I have some jobs using two lists in parallel then disposing them. Afterwards (on the same handle) I'm allocating a queue and assigning its ParallelWriter to a new job. That job failed with the InvalidOperationException.

    As noted in the code above if I do a handle.Complete() after scheduling the two dispose then there isn't any issues.

    As far as I can tell I'm following patterns just fine. Is this a bug?
     
  2. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    1,692
    Posted code works fine without any errors, are you sure this is problem place?

    upload_2019-10-2_14-58-52.png
    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using Unity.Collections;
    5. using Unity.Jobs;
    6. using UnityEngine;
    7.  
    8. public class TestJob : MonoBehaviour
    9. {
    10.     private struct OneJob : IJobParallelFor
    11.     {
    12.         public NativeQueue<int>.ParallelWriter writer;
    13.  
    14.         public void Execute(int index)
    15.         {
    16.             writer.Enqueue(index);
    17.         }
    18.     }
    19.  
    20.     private struct ListJob : IJob
    21.     {
    22.         public NativeList<int> list;
    23.  
    24.         public void Execute()
    25.         {
    26.             for (int i = 0; i < 100; i++)
    27.             {
    28.                 list.Add(i);
    29.                 ;
    30.             }
    31.  
    32.             Debug.Log("Inside List Job");
    33.         }
    34.     }
    35.  
    36.     private void Update()
    37.     {
    38.         JobHandle handle = default;
    39.  
    40.         NativeList<int> list1 = new NativeList<int>(100, Allocator.TempJob);
    41.  
    42.         ListJob listJob1 = new ListJob();
    43.         listJob1.list = list1;
    44.  
    45.         JobHandle listHandle1 = listJob1.Schedule(handle);
    46.  
    47.         NativeList<int> list2 = new NativeList<int>(100, Allocator.TempJob);
    48.  
    49.         ListJob listJob2 = new ListJob();
    50.         listJob2.list = list2;
    51.  
    52.         JobHandle listHandle2 = listJob2.Schedule(handle);
    53.  
    54.         handle = JobHandle.CombineDependencies(listHandle1,           listHandle2);
    55.         handle = JobHandle.CombineDependencies(list1.Dispose(handle), list2.Dispose(handle));
    56.  
    57.         NativeQueue<int> queue = new NativeQueue<int>(Allocator.TempJob);
    58.  
    59.         OneJob job = new OneJob();
    60.         job.writer = queue.AsParallelWriter();
    61.  
    62.         handle = job.Schedule(43, 16, handle);
    63.         handle = queue.Dispose(handle);
    64.  
    65.         handle.Complete();
    66.  
    67.         Debug.Log("Update End");
    68.     }
    69. }
    70.  
     
  3. cjddmut

    cjddmut

    Joined:
    Nov 19, 2012
    Posts:
    120
    Unfortunately I'm not quite so lucky :) I created a new project and updated 2019.2.7f2 and the problem remains. I used your (slightly) modified script exactly.

    upload_2019-10-2_9-25-23.png

    I had another teammate try it and they hit the issue as well.

    The blank project has just 0.1.1 Collections package installed.
     
  4. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    1,692
    I’m on 2019.3
     
  5. cjddmut

    cjddmut

    Joined:
    Nov 19, 2012
    Posts:
    120
    Upgrading the blank project to 2019.3 has resolved the issue. I'll move the actual project over and see that resolves it as well.

    Thanks!
     
unityunity