Как выполнить двойную буферизацию с помощью атомных указателей?
Атомный новичок здесь. Мой код в настоящее время выглядит так (упрощенно):
std::atomic<Object*> object;
void thread_a()
{
object.load()->doSomething(); // (1)
}
void thread_b()
{
Object* oldObject = object.load();
Object* newObject = new Object();
// Update new object accordingly...
while (!object.compare_exchange_weak(oldObject, newObject));
delete oldObject;
}
Словом, моя идея состоит в том, чтобы позволить thread_b
атомарно поменять общий объект (двойная буферизация), в то время как thread_a
выполняет с ним некоторую работу. Мой вопрос: могу ли я предположить, что общий объект будет "защищен" от гонок данных, в то время как thread_a
вызывает для него doSomething()
, как это сделано в (1)?
Ответы
Ответ 1
Извлечение указателя с помощью load()
будет атомарным, но сам вызов doSomething()
не будет атомарным.
Это означает, что указатели можно поменять местами после doSomething()
load()
но перед doSomething()
(что означает, что doSomething()
вызывается с неправильным и теперь удаленным объектом).
Возможно, мьютекс может быть лучшим выбором здесь?
Ответ 2
Я делаю это довольно часто, но... с общими указателями и без блокировки!
Есть проблема с вашим дизайном, как предложил какой-то программист Чувак в своем ответе. Но если вы сделаете это с shared_ptr
, и логика вашей программы это позволит, у вас все будет хорошо.
Причина, по которой это работает с shared_ptr
заключается в том, что ваш объект не будет удален принудительно, пока он живет где-то еще. Итак, вот как вы это делаете:
std::shared_ptr<Object> object;
void thread_a()
{
std::atomic_load(&object)->doSomething(); // (1)
}
void thread_b()
{
std::shared_ptr<Object> oldObject = std::atomic_load(&object);
std::shared_ptr<Object> newObject = std::make_shared<Object>();
// Update new object accordingly...
while (!std::atomic_compare_exchange_weak(object, oldObject, newObject));
}
РЕДАКТИРОВАТЬ: Этот atomic_load
специализируется для shared_ptr
. Это, кажется, вызвало путаницу в комментариях: https://en.cppreference.com/w/cpp/memory/shared_ptr/atomic