How to perform double buffering with atomic pointers?
Clash Royale CLAN TAG#URR8PPP
up vote
6
down vote
favorite
Atomic newbie here. My code currently looks like this (simplified):
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 words, my idea is to let thread_b
atomically swap the shared object (double-buffering), while thread_a
performs some work on it. My question: can I safely assume that the shared object will be "protected" against data races while thread_a
calls doSomething()
on it, as done in (1)?
c++ multithreading atomic
add a comment |Â
up vote
6
down vote
favorite
Atomic newbie here. My code currently looks like this (simplified):
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 words, my idea is to let thread_b
atomically swap the shared object (double-buffering), while thread_a
performs some work on it. My question: can I safely assume that the shared object will be "protected" against data races while thread_a
calls doSomething()
on it, as done in (1)?
c++ multithreading atomic
add a comment |Â
up vote
6
down vote
favorite
up vote
6
down vote
favorite
Atomic newbie here. My code currently looks like this (simplified):
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 words, my idea is to let thread_b
atomically swap the shared object (double-buffering), while thread_a
performs some work on it. My question: can I safely assume that the shared object will be "protected" against data races while thread_a
calls doSomething()
on it, as done in (1)?
c++ multithreading atomic
Atomic newbie here. My code currently looks like this (simplified):
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 words, my idea is to let thread_b
atomically swap the shared object (double-buffering), while thread_a
performs some work on it. My question: can I safely assume that the shared object will be "protected" against data races while thread_a
calls doSomething()
on it, as done in (1)?
c++ multithreading atomic
c++ multithreading atomic
asked 2 hours ago


Ignorant
345620
345620
add a comment |Â
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
7
down vote
The fetching of the pointer with load()
will be atomic, but the call to doSomething()
itself will not be atomic.
That means the pointers could be swapped after load()
is called but before doSomething()
is called (which means doSomething()
is called on the wrong and now deleted object).
Perhaps a mutex could be a better choice here?
Yes, a mutex would definitely be a better/easier choice :) However I'm trying to investigate the lock-free way of doing this kind of things. Is the atomic double-buffering not doable in your opinion?
– Ignorant
2 hours ago
@Ignorant IMO not the way you have implemented it anyway. Perhaps if you used smart pointers (e.g.std::unique_ptr<Object>
) instead. Then the worst that could happen is that you calldoSomething()
on an object that isn't "active" but at least it will still exist.
– Some programmer dude
2 mins ago
add a comment |Â
up vote
2
down vote
I do this quite often, but... with shared pointers, and it's lock-free!
There's a problem with your design, as Some Programmer Dude suggested in his answer. But if you do this with shared_ptr
, and your program logic allows it, you'll be fine.
The reason why this works with shared_ptr
is that your object will not be deleted by force, as long as it lives somewhere else. So, this is how you do it:
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));
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
7
down vote
The fetching of the pointer with load()
will be atomic, but the call to doSomething()
itself will not be atomic.
That means the pointers could be swapped after load()
is called but before doSomething()
is called (which means doSomething()
is called on the wrong and now deleted object).
Perhaps a mutex could be a better choice here?
Yes, a mutex would definitely be a better/easier choice :) However I'm trying to investigate the lock-free way of doing this kind of things. Is the atomic double-buffering not doable in your opinion?
– Ignorant
2 hours ago
@Ignorant IMO not the way you have implemented it anyway. Perhaps if you used smart pointers (e.g.std::unique_ptr<Object>
) instead. Then the worst that could happen is that you calldoSomething()
on an object that isn't "active" but at least it will still exist.
– Some programmer dude
2 mins ago
add a comment |Â
up vote
7
down vote
The fetching of the pointer with load()
will be atomic, but the call to doSomething()
itself will not be atomic.
That means the pointers could be swapped after load()
is called but before doSomething()
is called (which means doSomething()
is called on the wrong and now deleted object).
Perhaps a mutex could be a better choice here?
Yes, a mutex would definitely be a better/easier choice :) However I'm trying to investigate the lock-free way of doing this kind of things. Is the atomic double-buffering not doable in your opinion?
– Ignorant
2 hours ago
@Ignorant IMO not the way you have implemented it anyway. Perhaps if you used smart pointers (e.g.std::unique_ptr<Object>
) instead. Then the worst that could happen is that you calldoSomething()
on an object that isn't "active" but at least it will still exist.
– Some programmer dude
2 mins ago
add a comment |Â
up vote
7
down vote
up vote
7
down vote
The fetching of the pointer with load()
will be atomic, but the call to doSomething()
itself will not be atomic.
That means the pointers could be swapped after load()
is called but before doSomething()
is called (which means doSomething()
is called on the wrong and now deleted object).
Perhaps a mutex could be a better choice here?
The fetching of the pointer with load()
will be atomic, but the call to doSomething()
itself will not be atomic.
That means the pointers could be swapped after load()
is called but before doSomething()
is called (which means doSomething()
is called on the wrong and now deleted object).
Perhaps a mutex could be a better choice here?
edited 2 hours ago
answered 2 hours ago


Some programmer dude
287k24235396
287k24235396
Yes, a mutex would definitely be a better/easier choice :) However I'm trying to investigate the lock-free way of doing this kind of things. Is the atomic double-buffering not doable in your opinion?
– Ignorant
2 hours ago
@Ignorant IMO not the way you have implemented it anyway. Perhaps if you used smart pointers (e.g.std::unique_ptr<Object>
) instead. Then the worst that could happen is that you calldoSomething()
on an object that isn't "active" but at least it will still exist.
– Some programmer dude
2 mins ago
add a comment |Â
Yes, a mutex would definitely be a better/easier choice :) However I'm trying to investigate the lock-free way of doing this kind of things. Is the atomic double-buffering not doable in your opinion?
– Ignorant
2 hours ago
@Ignorant IMO not the way you have implemented it anyway. Perhaps if you used smart pointers (e.g.std::unique_ptr<Object>
) instead. Then the worst that could happen is that you calldoSomething()
on an object that isn't "active" but at least it will still exist.
– Some programmer dude
2 mins ago
Yes, a mutex would definitely be a better/easier choice :) However I'm trying to investigate the lock-free way of doing this kind of things. Is the atomic double-buffering not doable in your opinion?
– Ignorant
2 hours ago
Yes, a mutex would definitely be a better/easier choice :) However I'm trying to investigate the lock-free way of doing this kind of things. Is the atomic double-buffering not doable in your opinion?
– Ignorant
2 hours ago
@Ignorant IMO not the way you have implemented it anyway. Perhaps if you used smart pointers (e.g.
std::unique_ptr<Object>
) instead. Then the worst that could happen is that you call doSomething()
on an object that isn't "active" but at least it will still exist.– Some programmer dude
2 mins ago
@Ignorant IMO not the way you have implemented it anyway. Perhaps if you used smart pointers (e.g.
std::unique_ptr<Object>
) instead. Then the worst that could happen is that you call doSomething()
on an object that isn't "active" but at least it will still exist.– Some programmer dude
2 mins ago
add a comment |Â
up vote
2
down vote
I do this quite often, but... with shared pointers, and it's lock-free!
There's a problem with your design, as Some Programmer Dude suggested in his answer. But if you do this with shared_ptr
, and your program logic allows it, you'll be fine.
The reason why this works with shared_ptr
is that your object will not be deleted by force, as long as it lives somewhere else. So, this is how you do it:
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));
add a comment |Â
up vote
2
down vote
I do this quite often, but... with shared pointers, and it's lock-free!
There's a problem with your design, as Some Programmer Dude suggested in his answer. But if you do this with shared_ptr
, and your program logic allows it, you'll be fine.
The reason why this works with shared_ptr
is that your object will not be deleted by force, as long as it lives somewhere else. So, this is how you do it:
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));
add a comment |Â
up vote
2
down vote
up vote
2
down vote
I do this quite often, but... with shared pointers, and it's lock-free!
There's a problem with your design, as Some Programmer Dude suggested in his answer. But if you do this with shared_ptr
, and your program logic allows it, you'll be fine.
The reason why this works with shared_ptr
is that your object will not be deleted by force, as long as it lives somewhere else. So, this is how you do it:
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));
I do this quite often, but... with shared pointers, and it's lock-free!
There's a problem with your design, as Some Programmer Dude suggested in his answer. But if you do this with shared_ptr
, and your program logic allows it, you'll be fine.
The reason why this works with shared_ptr
is that your object will not be deleted by force, as long as it lives somewhere else. So, this is how you do it:
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));
edited 1 hour ago
answered 1 hour ago


The Quantum Physicist
10.4k64392
10.4k64392
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53061020%2fhow-to-perform-double-buffering-with-atomic-pointers%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password