I have a bunch of threads doing work on multiple data items. The threads have to put out the results in the same order I hand data to the threads. That is:
Thread #1: give data - start processing
Thread #2: give data - start processing
Thread #3: give data - start processing
...
Thread #n: give data - start processing
The results should be retrieved in the same order the data was passed to the threads regardless of which thread finished processing first. Namely:
Thread #1: put data
Thread #2: put data
...
To differentiate between threads and manage them, I gave each one an ID (0,1,2,...,n). I am using the IDs to assign data to each thread so it can process it.
for(int i=0; i<thread_count; i++)
give_data(i); // i is id and the function knows where to get data from
I want the threads to share a token which determines which thread is expected to produce the result. All thread bodies are identical, the body looks like:
while(true){
auto data = get_data();
result = process_data(data);
while(token != this_id) spin;
put_data(result); // this is a synchronized call
update_token(token);
}
My issue comes with the token. I first tried a normal reference (int & token) and it obviously cannot work (and I didn't expect it to). Anyway, I used a static variable and the threads do not always get the latest one. I was surprised to see one thread dominating everything. Whenever a thread updates the token, it loses its turn allowing another thread to put its result and so on. However, I had one thread dominating as if the token is always set to its own ID and not updating.
If I had to guess I would say it's a caching issue. However, I am not sure.
Anyway, I am thinking of using std::atomic<int> as my token. Would it work? If not, what else should I consider doing? What would be a better way to synchronize those threads?
Extra: this feels like a bad design and I am not sure how to do it better. Any suggestions would be very much appreciated.