У меня есть несколько структур данных, которые я выделяю в куче, которые редко изменяются, но требуют быстрого доступа для чтения. Одним из примеров может быть структура, размещенная в куче, к которой многие потоки обращаются очень часто только для чтения. Периодически эту структуру нужно переписывать, и чтобы избежать блокировки, я задавался вопросом, безопасно ли ее использовать auto_ptr
в основном, чтобы потоки, получившие ссылку, могли продолжать обработку до тех пор, пока они не закончили, но позволяя автору записи сделать копию структуры, переписать ее и быстро поменять указатели на новые auto_ptr
экземпляр структуры.
Я получил эту идею от CopyOnWriteArrayList
в Java и надеется выполнить что-то аналогичное в C ++.
std::auto_ptr
не имеет никаких гарантий безопасности потока при вызове неконстантного члена, такого как reset()
как вы предлагаете. Более того, ни один не делает std::unique_ptr
который вы должны рассмотреть в качестве замены auto_ptr
как auto_ptr
эффективно устарела.
std::shared_ptr
делает предоставить такие гарантии безопасности.
На что вы обычно гарантированы shared_ptr
является то, что счетчик ссылок управляется атомарным способом, что означает, что вы защищены от гонок данных при создании копии shared_ptr
при условии, что в настоящее время никто не изменяет shared_ptr
в тот самый момент.
Рассмотрим следующий вариант использования для вашего shared_ptr
, У вас есть глобальный shared_ptr<string> sharedString;
который в настоящее время указывает на экземпляр std::string
, Для многих потоков безопасно вызывать get()
получить указатель на строку. Они также могут создать свой собственный общий указатель на него следующим образом: shared_ptr<string> myString = sharedString;
при условии, что никто не меняет то, на что указывает общий указатель.
Теперь давайте вернемся и исправим состояние гонки, которое существует в примере. Когда приходит время изменить то, на что указывает глобальный общий указатель, поток может сделать его копию — это проблема, поскольку он может оставить копию в несогласованном состоянии. Итак, мы должны убедиться, что мы изменили и скопировали это атомарно.
К счастью для нас, shared_ptr
предоставляет ряд специализаций атомарных операций C ++ 11: atomic_load
, atomic_store
, а также atomic_exchange
.
При создании копии shared_ptr
использовать atomic_load
и при обновлении shared_ptr
использовать atomic_store
,
Делать это таким образом важно по двум причинам.
Теперь важно отметить, что использование потоковых операций на shared_ptr
не обеспечивает никакой безопасности потока для типа, на который он указывает. Вы всегда должны позаботиться о том, чтобы указанный объект использовался в поточно-ориентированном режиме.
Вы можете переназначить auto_ptr на лету с помощью reset (), кстати, он уничтожает ранее указанный объект.
Тем не менее, auto_ptr устарела, так как unique_ptr имеет функцию swap (), которая, похоже, немного соответствует тому, что вы ищете.
Имейте в виду, что эти классы не потокобезопасный.