Search Unity

Is it possible to Iterate through a bunch of NativeQueues?

Discussion in 'Entity Component System' started by calabi, Jul 20, 2021.

  1. calabi

    calabi

    Joined:
    Oct 29, 2009
    Posts:
    232
    So I need a bunch of separate NativeQueues of the same type and I'm wondering if its possible to iterate through them all in a Foreach loop or even a For loop as if they are all the same objects. Is it possible to put them into a container for that or maybe this won't work at all and I need to look at some other data structure?
     
  2. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,271
    You can pack them into a struct with a custom indexer.
     
    calabi likes this.
  3. calabi

    calabi

    Joined:
    Oct 29, 2009
    Posts:
    232
    I didn't realise I could do that, I guess I create them outside the struct and then I can put them into whatever structure I want and get them out that whatever way I want. That's great thanks.
     
  4. calabi

    calabi

    Joined:
    Oct 29, 2009
    Posts:
    232
    Sorry for the quote but I am kind of confused, I just want to check my thinking is along the correct lines. My thought is to just put them into a basic array or list roughly like below.

    Code (CSharp):
    1. public struct StoreandIterateQueues
    2. {
    3.     public bool InputValues(NativeQueue<RobotcopyGUID> currentnative, NativeQueue<RobotcopyGUID> [] nativesqueues)
    4.     {
    5.         bool hasitworked = false;
    6.  
    7.         for (int i = 0; i < nativesqueues.Length; i++)
    8.         {
    9.               //assign to nativequeus here
    10.         }
    11.          
    12.  
    13.         return hasitworked;
    14.     }
    But it won't be burst compatible will and I don't think it will work in general. All the custom indexers I've googled involve code inside the custom class which I can't do in this case. So I'm not sure what direction to head in, any hints would be appreciated.
     
    Last edited: Jul 21, 2021
  5. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,271
    Code (CSharp):
    1. public struct PackedQueues
    2. {
    3.     NativeQueue<int> q0;
    4.     NativeQueue<int> q1;
    5.     NativeQueue<int> q2;
    6.     NativeQueue<int> q3;
    7.  
    8.     public NativeQueue<int> this[int i]
    9.     {
    10.         get
    11.         {
    12.              switch (i)
    13.              {
    14.                  case 0: return q0;
    15.                  case 1: return q1;
    16.                  case 2: return q2;
    17.                  case 3: return q3;
    18.                  default: return default;
    19.               }
    20.          }
    21.          set
    22.          {
    23.              switch (i)
    24.              {
    25.                  case 0: q0 = value; break;
    26.                  case 1: q1 = value; break;
    27.                  case 2: q2 = value; break;
    28.                  case 3: q3 = value; break;
    29.               }
    30.          }
    31.     }
    32. }          
     
    calabi likes this.
  6. calabi

    calabi

    Joined:
    Oct 29, 2009
    Posts:
    232
    That's awesome thanks for the example @DreamingImLatios, thats completely different to what I thought, but it works better than my ways(I did briefly, a couple of seconds think of doing something similar using ELSE IF's but dismissed it).
     
  7. MintTree117

    MintTree117

    Joined:
    Dec 2, 2018
    Posts:
    340
    You can have a NativeArray/NativeList of UnsafeQueues. Unsafe Containers are under Unity.Collections.LowLevel.Unsafe and are the same as Native Containers but without safety checks. You can nest these.
     
    calabi likes this.
  8. calabi

    calabi

    Joined:
    Oct 29, 2009
    Posts:
    232
    I didn't think of the unsafe lists I guess I could try using them I mostly know what I'm doing.
     
  9. MintTree117

    MintTree117

    Joined:
    Dec 2, 2018
    Posts:
    340
    Just remember arrays and lists return by value not by reference. So you will need to explicitly access the queues by reference or use pointer, or copy then write back.
     
  10. calabi

    calabi

    Joined:
    Oct 29, 2009
    Posts:
    232
    I guess I'm kind of confused then, what do I pass as a reference or pointer I've tried all the combinations I can think of and am missing the correct one, or what exactly do I write back to what.

    Code (CSharp):
    1.  
    2.         var somink = new RobotcopyGUID { IntVal = 2222 };
    3.         var othersomink = new RobotcopyGUID { IntVal = 5555 };
    4.         var jeebus = new RobotcopyGUID { IntVal = 7777 };
    5.  
    6. NativeArray<UnsafeRingQueue<RobotcopyGUID>> willthiswork = new NativeArray<UnsafeRingQueue<RobotcopyGUID>>(3, Allocator.Temp);
    7.  
    8.         willthiswork[0] = new UnsafeRingQueue<RobotcopyGUID>(3, Allocator.Temp);
    9.         willthiswork[1] = new UnsafeRingQueue<RobotcopyGUID>(3, Allocator.Temp);
    10.         willthiswork[2] = new UnsafeRingQueue<RobotcopyGUID>(3, Allocator.Temp);
    11.  
    12.         willthiswork[0].Enqueue(somink);    
    13.         willthiswork[1].Enqueue(othersomink);
    14.         willthiswork[2].Enqueue(jeebus);
    15.  
    16.         for (int j = 0; j < 3; j++)
    17.         {        
    18.             RobotcopyGUID dumpydoo = new RobotcopyGUID();
    19.             Debug.Log("The values are " + willthiswork[j].Length + willthiswork[j].TryDequeue(out dumpydoo));
    20.         }
    I've tried the above test code but clearly it doesn't work because its accessing by value. The length always remains zero and Dequeue always returns false.
     
  11. calabi

    calabi

    Joined:
    Oct 29, 2009
    Posts:
    232
    Neh mind Instead of doing.

    Code (CSharp):
    1. willthiswork[0] = new UnsafeRingQueue<RobotcopyGUID>(3, Allocator.Temp);
    I did.

    Code (CSharp):
    1. var tempallvar = new UnsafeRingQueue<RobotcopyGUID>(3, Allocator.Temp);
    2.                         tempallvar.Enqueue(somink);
    3.                          willthiswork[0] = tempallvar;
    4.  
     
  12. MintTree117

    MintTree117

    Joined:
    Dec 2, 2018
    Posts:
    340
    By pointer reference:

    Code (CSharp):
    1. var array = new NativeArray<UnsafeQueue>();
    2.  
    3. ref var q = ref UnsafeUtility.ArrayElementAsRef(array.UnsafePointer(), index);
    4. q.Enqueue();
    5.  
    Or by value and write:

    Code (CSharp):
    1. var temp = array[0];
    2.  
    3. temp.Enqueue();
    4.  
    5. array[0] = temp;
    Or by raw pointers I think this is how you do it?

    Code (CSharp):
    1. var array = new NativeArray<UnsafeQueue>();
    2.  
    3. var pointer = array.UnsafePointer();
    4. var sizeOfQueue;
    5. var index;
    6.  
    7. var queue =  *((UnsafeQueue*)(pointer + index * sizeOfQueue));
    8. queue->enqueue;
     
    Last edited: Jul 26, 2021
    calabi likes this.