Assume I have a thread-safe collection of Things (call it a ThingList), and I want to add the following function.
Thing * ThingList::findByName(string name)
{
return &item[name]; // or something similar..
}
But by doing this, I've delegated the responsibility for thread safety to the calling code, which would have to do something like this:
try
{
list.lock(); // NEEDED FOR THREAD SAFETY
Thing *foo = list.findByName("wibble");
foo->Bar = 123;
list.unlock();
}
catch (...)
{
list.unlock();
throw;
}
Obviously a RAII lock/unlock object would simplify/remove the try/catch/unlocks, but it's still easy for the caller to forget.
There are a few alternatives I've looked at:
- Return Thing by value, instead of a pointer - fine unless you need to modify the Thing
- Add function
ThingList::setItemBar(string name, int value)
- fine, but these tend to proliferate - Return a pointerlike object which locks the list on creation and unlocks it again on destruction. Not sure if this is good/bad practice...
What's the right approach to dealing with this?