Search Unity

increment counter in IJobForEach<>

Discussion in 'Data Oriented Technology Stack' started by francois85, Aug 14, 2019.

  1. francois85

    francois85

    Joined:
    Aug 11, 2015
    Posts:
    573
    Looking for the correct way to increment int i in IJobForEach . I feel like Ive seem people handle this but cant find where.

    Code (CSharp):
    1.        
    2. struct SomeTest : IJobForEach<TriangleComponent>
    3.         {
    4.             [DeallocateOnJobCompletion]                    
    5.             public NativeArray<Vector3> VertcesBuffer;
    6.             [DeallocateOnJobCompletion]
    7.             [ReadOnly]  
    8.             public NativeArray<VertexComponent> VertexComponentData;
    9.    
    10.             public void Execute([ReadOnly] ref TriangleComponent t)
    11.             {
    12.                 VertcesBuffer[3 * i + 0].x = VertexComponentData[t.VertA].PositionX;
    13.                 VertcesBuffer[3 * i + 0].y = VertexComponentData[t.VertA].PositionY;
    14.                 VertcesBuffer[3 * i + 0].z = VertexComponentData[t.VertA].PositionZ;
    15.  
    16.                 // NEED i++ ?????????????????????????????
    17.             }
    18.         }
    19.  
     
  2. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    1,560
  3. francois85

    francois85

    Joined:
    Aug 11, 2015
    Posts:
    573
  4. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    1,370
    Why just not use IJobForEachWitEntity and use it Index argument?
     
  5. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    1,370
  6. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    1,560
    Oh crap I forgot they changed the version and it differs from what I used ot use.

    The original returned the index on Increment. Let me find it.

    The older version looked like this

    Code (CSharp):
    1. public int Increment()
    2. {
    3.     #if ENABLE_UNITY_COLLECTIONS_CHECKS
    4.         AtomicSafetyHandle.CheckWriteAndThrow(m_Safety);
    5.     #endif
    6.  
    7.     int incrementedValue = Interlocked.Increment(ref *m_Counter);
    8.     return incrementedValue;
    9. }
    Where the increment was done with a lock. But they changed it to be lock less when they added it as a sample.

    (You can't just change that code btw, this version uses local per thread count which is why it's lockless. I'll try find the version with a lock that returns the index when I get a sec)

    -edit-

    Actually it's still there on the manual

    It's the first implementation

    Code (CSharp):
    1. [NativeContainer]
    2. // This attribute is what makes it possible to use NativeCounter.Concurrent in a ParallelFor job
    3. [NativeContainerIsAtomicWriteOnly]
    4. unsafe public struct Concurrent
    5. {
    6.     // Copy of the pointer from the full NativeCounter
    7.     [NativeDisableUnsafePtrRestriction]
    8.     int*    m_Counter;
    9.  
    10.     // Copy of the AtomicSafetyHandle from the full NativeCounter. The dispose sentinel is not copied since this inner struct does not own the memory and is not responsible for freeing it.
    11. #if ENABLE_UNITY_COLLECTIONS_CHECKS
    12.     AtomicSafetyHandle m_Safety;
    13. #endif
    14.  
    15.     // This is what makes it possible to assign to NativeCounter.Concurrent from NativeCounter
    16.     public static implicit operator NativeCounter.Concurrent (NativeCounter cnt)
    17.     {
    18.         NativeCounter.Concurrent concurrent;
    19. #if ENABLE_UNITY_COLLECTIONS_CHECKS
    20.         AtomicSafetyHandle.CheckWriteAndThrow(cnt.m_Safety);
    21.         concurrent.m_Safety = cnt.m_Safety;
    22.         AtomicSafetyHandle.UseSecondaryVersion(ref concurrent.m_Safety);
    23. #endif
    24.  
    25.         concurrent.m_Counter = cnt.m_Counter;
    26.         return concurrent;
    27.     }
    28.  
    29.     public void Increment()
    30.     {
    31.         // Increment still needs to check for write permissions
    32. #if ENABLE_UNITY_COLLECTIONS_CHECKS
    33.         AtomicSafetyHandle.CheckWriteAndThrow(m_Safety);
    34. #endif
    35.         // The actual increment is implemented with an atomic, since it can be incremented by multiple threads at the same time
    36.         Interlocked.Increment(ref *m_Counter);
    37.     }
    38. }
    But change the Concurrent Increment to return the value from Interlocked.Increment (or -1)
     
    Last edited: Aug 14, 2019