The use case is this:
- One thread writes data, using SetData()
- Multiple threads may read data, using GetData()
- I plan to only use basic data types or structs as T
With these rules in mind, is this thread safe?
public struct ThreadSafeData<T>
{
private T[] dataArray;
private int setterIndex;
private int lastSetIndex;
public void Init()
{
dataArray = new T[2];
}
public void SetData(T data)
{
dataArray[setterIndex] = data;
lastSetIndex = setterIndex;
// Convert 0 to 1, and 1 to 0
setterIndex = lastSetIndex * - 1 + 1;
}
public T GetData()
{
return dataArray[lastSetIndex];
}
}
UPDATE (requested in comments)
What I would like to achieve is the following; I want to avoid tearing and want the reader to always read the last value written by the writer. I tried doing that with a single T field, but then I encountered (what I think is) tearing. For example, in the tests (see below) I always write a Vector2Int with 0,0 or 1,1. But the reader would sometimes read 1,0 when using a single T field. This is why I added the Array (and added the "data integrity" check to my tests).
I am using X64 architecture. And this is the Vector2Int I use in my tests: https://docs.unity3d.com/ScriptReference/Vector2Int.html
Questions
How do I know if this is thread safe (if it is)? I have run tests for quite a while. But how do I know for sure?
Do you know a better solution for this use case? Please let me know!
Tests
I am making a game in Unity and have run tests where the "writing thread" runs at 30, 60 or 90fps, and doing up to 300 writes per frame. And a "reading thread" running from 30 to 300fps (doing 1 read per frame).
The test data (T) I used was a struct with a Vector2Int and a bool. To check the data integrity, the "reader" checked if the x and y of the Vector2Int are 1 when the bool is true and when false, x and y have to be 0 (it throws an error when this is wrong).
I ran these test for about an hour and never got any errors. But I am not sure if that means that this always works correct.
(ps. I don't really care if this template is a struct or class; I am not sure yet what will work best for me)