Wie führt man eine doppelte Pufferung mit atomaren Zeigern durch?

Wie führt man eine doppelte Pufferung mit atomaren Zeigern durch?


Atomic-Neuling hier. Mein Code sieht derzeit so aus (vereinfacht):


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;
}

In Worten, meine Idee ist, thread_b zu lassen tauschen Sie das gemeinsam genutzte Objekt atomar aus (doppelte Pufferung), während thread_a führt einige Arbeiten daran durch. Meine Frage:Kann ich sicher davon ausgehen, dass das gemeinsam genutzte Objekt während thread_a gegen Data Races "geschützt" ist ruft doSomething() auf darauf, wie in (1) getan?


Antworten:


Das Holen des Zeigers mit load() wird atomar sein, aber der Aufruf von doSomething() selbst wird nicht atomar sein.


Das bedeutet, dass die Zeiger nach load() vertauscht werden könnten aufgerufen wird, aber vor doSomething() aufgerufen wird (was doSomething() bedeutet wird auf dem falschen und nun gelöschten Objekt aufgerufen).


Vielleicht wäre hier ein Mutex die bessere Wahl?


Einige Code-Antworten


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;
}
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));
}