I have read many of the questions already answered that relate to this but none of them gave me a clear understanding of which I should be using when I have multiple writers but a single reader. The code below is a contrived example of what I'm talking about.
struct StateInfo {
long wd{};
uint32_t perc{};
};
class Blah
{
const int numDevices = getDevices();
std::shared_mutex sharedMutexSI_;
vector<StateInfo> stateInfo;
public:
Blah() : stateInfo(numDevices){};
void writers(StateInfo &newSi, const int i)
{
std::shared_lock<std::shared_mutex> _MULTIPLE(sharedMutexSI_);
stateInfo[i] = newSi;
}
StateInfo reader(const int i)
{
std::lock_guard<std::shared_mutex> _EXCLUSIVE(sharedMutexSI_);
return stateInfo[i];
}
};
The situation is that multiple writers may simultaneously update the stateInfo vector but never the same item in the vector as i
is unique to each thread. A single reader thread may at any time try to read any of the vector items.
Is the above code correct in avoiding race conditions?
Is lock_guard
the right one to use or should I use scoped_lock
or unique_lock
?
To summarize what was already written in comments:
Yes, the code is correct. However, it may be inefficient, because it disallows reading from any array element while writing to another array element. You might want to do more fine-grained synchronization by using a mutex
for each array element.
class Blah
{
const int numDevices = getDevices();
std::vector<std::mutex> mutexes;
std::vector<StateInfo> stateInfo;
public:
Blah() : mutexes(numDevices), stateInfo(numDevices){}
void writers(StateInfo &newSi, const int i)
{
std::lock_guard<std::mutex> guard(mutexes[i]);
stateInfo[i] = newSi;
}
StateInfo reader(const int i)
{
std::lock_guard<std::mutex> guard(mutexes[i]);
return stateInfo[i];
}
};