Предположим, что у меня есть потокобезопасная коллекция вещей (назовите ее ThingList), и я хочу добавить следующую функцию.Возвращаемые указатели потокобезопасным способом
Thing * ThingList::findByName(string name)
{
return &item[name]; // or something similar..
}
Но, делая это, я делегировал ответственность за безопасность потока в код вызова, который должен был бы сделать что-то вроде этого:
try
{
list.lock(); // NEEDED FOR THREAD SAFETY
Thing *foo = list.findByName("wibble");
foo->Bar = 123;
list.unlock();
}
catch (...)
{
list.unlock();
throw;
}
Очевидно, что замок RAII/разблокировать объект будет упростить/удалить try/catch/unlocks, но для абонента все же легко забыть.
Есть несколько альтернатив, я посмотрел на:
- Return Thing по значению, а не в указатель - отлично, если нет необходимости в изменить Thing
- Добавить функцию
ThingList::setItemBar(string name, int value)
- отлично, но они имеют тенденцию к proliferate - Верните указательный объект, который блокирует список при создании и разблокирует его снова при уничтожении. Не уверен, что это хорошая/плохая практика ...
Каков правильный подход к решению этой проблемы?
«Объединить» это хорошо, но есть скрытое предположение, что объекты Thing знают, как найдите себя в списке. Вы также можете передать «ключ» для слияния, но тогда у вас возникла проблема слияния элемента, который был удален ... – Roddy