У меня есть коллекция такой информации:
std::list< boost::shared_ptr<DataEntry> > m_Entries;
Доступ к списку осуществляется несколькими потоками. Большую часть времени список только для чтения, но иногда поток должен будет добавить или удалить записи из списка. Таким образом, сам список защищен блокировкой чтения / записи, но записи не защищены.
Сами отдельные записи в большинстве случаев являются неизменяемыми (с несколькими непостоянно изменяемыми элементами, которые по отдельности блокируются для предотвращения проблем параллелизма), и shared_ptr
s используются, чтобы гарантировать, что запись не будет удалена, пока ее читает поток, даже если другой поток удаляет запись из списка.
Характер доступа таков, что данный поток обычно будет обращаться к одной конкретной записи несколько раз, а иногда и к другой (изменяющейся) записи. Не имеет значения, устарели ли данные, если они не удаляются во время использования. В настоящее время каждый раз, когда ему нужна запись, он должен получить блокировку, выполнить поиск в списке, скопировать shared_ptr
, а затем снять блокировку. Нигде поток не может хранить указатель между доступами; он должен каждый раз отпускать и восстанавливать.
Как таковой, я думаю, что может быть выигрыш в производительности от кэширования наиболее часто используемой записи (как shared_ptr
или weak_ptr
) в локальном хранилище потока, чтобы избежать необходимости вообще блокировать блокировку в большинстве общий случай.
К сожалению, я использую VS2008, и его __declspec(thread)
не поддерживает типы не POD, такие как умные указатели. Я не могу сохранить пустой указатель, так как это не обеспечит гарантии отсутствия удаления, которые мне нужны. Я полагаю, что мог бы сохранить weak_ptr*
, но это привело бы к утечке памяти (и слабому количеству ссылок) при выходе из потока (хотя у меня есть ловушка, которая вызывается при "нормальном" выходе из потока, так что это может быть немного смягчено) , И, по понятным причинам, хранение shared_ptr*
будет еще хуже.
Учитывая сложность и то, что блокировки обычно не требуются, я не уверен, что возможное предельное повышение производительности стоит хлопот. Но мне было интересно, если я пропускаю лучший способ сделать это. (И мне также любопытно, если что-то улучшится в C ++ 11, поскольку в нем улучшена поддержка потоков.)