Атомарный доступ к ресурсам, хранящимся на карте

Я хочу сохранить некоторые экземпляры класса std::shared_ptr в С++ на карте, например. std::map, используя целочисленный ключ. Однако мне нужно, чтобы эта карта имела два свойства:

  1. Если ключ не существует, верните ошибку, а не создавайте новый объект.
  2. Если ключ существует, атомарно возьмите копию std::shared_ptr. т.е. не должно быть возможности удалить объект с карты в одном потоке, одновременно извлекая его с карты в другом.

Я хотел бы избежать одного мьютекса (даже многократного чтения, одной записи) для получения и удаления объектов с карты, если это возможно, чтобы избежать накладных расходов.

Существует ли такой класс карты в какой-либо библиотеке? Если нет, можете подсказать, как реализовать?


person user664303    schedule 25.02.2013    source источник
comment
см. примечания к ответу, который я дал на ваш 1-й вопрос здесь: (stackoverflow.com/questions/15053173/)   -  person πάντα ῥεῖ    schedule 27.02.2013


Ответы (2)


Если элементы внутри коллекции имеют мьютексы, вы можете просто использовать структуры данных без блокировки. Они реализованы на C++ в boost 1.53.0.

Однако я бы посоветовал еще раз взглянуть на мьютексы - во многих случаях они обеспечивают лучшую производительность структуры данных без блокировки (хотя и не всегда) и ими намного проще управлять. Пока нет цикла мьютексов, все должно быть в порядке.

При доступе без создания используйте std::map::find, если вы используете C++03 (возвращает итератор) или std::map::at если вы используете C++11 (возвращает ссылку).

EDIT: на самом деле std::map::at возможно хуже, если вы не предполагаете, что нормальный случай состоит в том, что элемент присутствует (т. е. против правила использовать исключения только для исключительного состояния вместо нормальной работы). Однако это, вероятно, зависит также от философии, применяемой к исключениям.

person Maciej Piechotka    schedule 25.02.2013
comment
Спасибо, но, к сожалению, вполне может быть цикл мьютексов. Я не нашел здесь подходящей структуры данных без блокировки: boost.org/doc/libs/1_53_0/doc/html/lockfree.html. Любые подсказки? - person user664303; 25.02.2013
comment
На самом деле не должно быть цикла мьютексов, потому что все, что я делаю, это копирую shared_ptr. Затем блокировка объекта захватывается только после освобождения мьютекса доступа к карте. Спасибо! - person user664303; 25.02.2013
comment
@ user664303: Обратите внимание, что вам нужно сделать: 1. заблокировать установленный мьютекс 2. найти и скопировать std::shared_ptr 3. разблокировать мьютекс. Если копия находится вне мьютекса, она может быть удалена с карты и стать последней ссылкой (удаление объекта). - person Maciej Piechotka; 25.02.2013

1) Используйте std::map::at. Это вызовет исключение, если ключ отсутствует

2) Используйте активный объект для доступа к карте. Активный объект заботится о сериализации операций и, таким образом, избегает условий гонки, но позволяет вам использовать старый добрый std::map.

person juanchopanza    schedule 25.02.2013
comment
@user664303 user664303 Есть несколько хороших ссылок здесь. Это отличная серия статей о параллелизме в современном C++. Одно из видео, я думаю, это может иметь пример реализации на С++ 11. - person juanchopanza; 25.02.2013
comment
Спасибо за ссылки. Я посмотрю видео. Однако в этом приложении мне не ясно, дает ли активный объект какие-либо преимущества по сравнению с одним мьютексом. Два объекта не могут быть извлечены одновременно, и возникнут накладные расходы. - person user664303; 25.02.2013