Возврат указателей ориентированным на многопотоковое исполнение способом

Предположите, что у меня есть ориентированный на многопотоковое исполнение набор Вещей (назовите его 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 блокирует/разблокирует объект, упростил бы/удалил бы пробование/ловление/разблокировать, но для вызывающей стороны все еще легко забыть.

Существует несколько альтернатив, на которые я посмотрел:

  • Возвратите Вещь значением вместо указателя - прекрасный, если Вы не должны изменять Вещь
  • Добавьте функцию ThingList::setItemBar(string name, int value) - прекрасный, но они имеют тенденцию распространяться
  • Возвратите подобный указателю объект, который блокирует список на создании и разблокировал его снова на разрушении. Не уверенный, если это - хорошая/плохая практика...

Что правильный подход к контакту с этим?

6
задан Roddy 19 April 2010 в 21:00
поделиться

2 ответа

Не существует единого «правильного подхода»; это зависит от потребностей вашего приложения.

Если возможно, возвращайте объекты по значению или возвращайте копию, с которой вызывающий может делать все, что захочет.

Вариант вышеизложенного - вернуть изменяемую копию, а затем предоставить способ атомарного слияния измененного объекта обратно в список. Что-то вроде:

Thing t = myThingList.getThing(key);
t.setFoo(f);
t.setBar(b);
myThingList.merge(t);     // ThingList atomically updates the appropriate element

Однако это может вызвать проблемы, если несколько потоков попытаются обновить один и тот же объект.

Идея «похожего на указатель объекта» звучит круто, но я подозреваю, что это приведет к труднодоступным ошибкам, если где-то не снимается какая-то блокировка.

Я бы попытался сохранить весь код блокировки / разблокировки в ThingList , поэтому функции ThingList :: set ... , вероятно, я бы сделал.

4
ответ дан 17 December 2019 в 00:06
поделиться

сохранить и вернуть boost :: shared_ptr s

вы должны заблокировать во время доступа, но вы в безопасности после разблокировки

3
ответ дан 17 December 2019 в 00:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: