Passing objects atomically across threads without locks or data races for audio synchronizationTwo threads...

School performs periodic password audits. Is my password compromised?

“I had a flat in the centre of town, but I didn’t like living there, so …”

What is a term for a function that when called repeatedly, has the same effect as calling once?

How do I deal with being envious of my own players?

Specific Chinese carabiner QA?

Deal the cards to the players

Can I solder 12/2 Romex to extend wire 5 ft?

Reason why dimensional travelling would be restricted

When do _WA_Sys_ statistics Get Updated?

Caulking a corner instead of taping with joint compound?

The need of reserving one's ability in job interviews

Split a number into equal parts given the number of parts

Being asked to review a paper in conference one has submitted to

Must 40/100G uplink ports on a 10G switch be connected to another switch?

Can a space-faring robot still function over a billion years?

Rationale to prefer local variables over instance variables?

PTIJ: Aharon, King of Egypt

When to use mean vs median

How does insurance birth control work?

Meaning of word ягоза

Should I use HTTPS on a domain that will only be used for redirection?

If nine coins are tossed, what is the probability that the number of heads is even?

Quitting employee has privileged access to critical information

Why doesn't "adolescent" take any articles in "listen to adolescent agonising"?



Passing objects atomically across threads without locks or data races for audio synchronization


Two threads working on shared dataPolymorphic STL foreach without passing the container typePass pointer data across multiple functionsPassing objects to functions safely and efficientlyQueue implementation without using built-in data structuresShare data and mutexes across threadsPassing C++ objects by reference for participants in a simulated battleSharing data between two threads C++Passing Objects of Classes to other ClassCRC without knowing the data type or size













1












$begingroup$


I am learning about one of the hardest parts of Audio development: the synchronization between the audio thread and the GUI thread. Per the discussion here https://forum.juce.com/t/timur-doumler-talks-on-c-audio-sharing-data-across-threads/26311 and here: https://stackoverflow.com/questions/15460829/lock-free-swap-of-two-unique-ptrt
I'm wondering if the following class solves the problem or comes close to solving it.



template<typename T>
struct SmartAtomicPtr
{
SmartAtomicPtr( T* newT )
{
update( newT );
}
~SmartAtomicPtr()
{
update(nullptr);
}
void update( T* newT, std::memory_order ord = memory_order_seq_cst )
{
keepAlive.reset( atomicTptr.exchange( newT, ord ) );
}
std::shared_ptr<T> getShared(std::memory_order ord = memory_order_seq_cst)
{
return std::make_shared<T>( atomicTptr.load(ord) );
}
T* getRaw(std::memory_order ord = memory_order_seq_cst)
{
return atomicTptr.load(ord);
}
private:
std::atomic<T*> atomicTptr{nullptr};
std::shared_ptr<T> keepAlive;
};


I know that whatever value ends up in the shared_ptr won't be deleted until the SmartAtomicPtr goes out of scope, which is fine.



the ultimate goal would be a lock-free, wait-free solution.



an example of where this might get used is the following interleaving of the audio and message thread. The goal is to keep the returned object from dangling



/*
AudioProcessor owns a SmartAtomicPtr<T> ptr that the message
thread has public access to.
*/
/* audio thread */ auto* t = ptr.getRaw();
/* message thread */ processor.ptr.update( new T() );
/* audio thread */ t->doSomething(); //t is a dangling pointer now


with getShared(), I believe that t no longer dangles:



/* audio thread */ auto t = ptr.getShared();
/* message thread */ processor.ptr.update( new T() );
/* audio thread */ t->doSomething(); //t is one of 2 shared_ptrs
//holding the previous atomic value of ptr


I ran into some double-deletes, but I believe I have solved them, and also prevented the shared_ptr member from being stomped on in the event you call getShared() and update() at the same time, and also kept it leak-free.



any thoughts?










share|improve this question









New contributor




MatkatMusic is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$












  • $begingroup$
    From C++20, there's std::atomic<shared_ptr<T>> partial specialization. You'll want to understand how it works if you're implementing your own.
    $endgroup$
    – Toby Speight
    9 hours ago


















1












$begingroup$


I am learning about one of the hardest parts of Audio development: the synchronization between the audio thread and the GUI thread. Per the discussion here https://forum.juce.com/t/timur-doumler-talks-on-c-audio-sharing-data-across-threads/26311 and here: https://stackoverflow.com/questions/15460829/lock-free-swap-of-two-unique-ptrt
I'm wondering if the following class solves the problem or comes close to solving it.



template<typename T>
struct SmartAtomicPtr
{
SmartAtomicPtr( T* newT )
{
update( newT );
}
~SmartAtomicPtr()
{
update(nullptr);
}
void update( T* newT, std::memory_order ord = memory_order_seq_cst )
{
keepAlive.reset( atomicTptr.exchange( newT, ord ) );
}
std::shared_ptr<T> getShared(std::memory_order ord = memory_order_seq_cst)
{
return std::make_shared<T>( atomicTptr.load(ord) );
}
T* getRaw(std::memory_order ord = memory_order_seq_cst)
{
return atomicTptr.load(ord);
}
private:
std::atomic<T*> atomicTptr{nullptr};
std::shared_ptr<T> keepAlive;
};


I know that whatever value ends up in the shared_ptr won't be deleted until the SmartAtomicPtr goes out of scope, which is fine.



the ultimate goal would be a lock-free, wait-free solution.



an example of where this might get used is the following interleaving of the audio and message thread. The goal is to keep the returned object from dangling



/*
AudioProcessor owns a SmartAtomicPtr<T> ptr that the message
thread has public access to.
*/
/* audio thread */ auto* t = ptr.getRaw();
/* message thread */ processor.ptr.update( new T() );
/* audio thread */ t->doSomething(); //t is a dangling pointer now


with getShared(), I believe that t no longer dangles:



/* audio thread */ auto t = ptr.getShared();
/* message thread */ processor.ptr.update( new T() );
/* audio thread */ t->doSomething(); //t is one of 2 shared_ptrs
//holding the previous atomic value of ptr


I ran into some double-deletes, but I believe I have solved them, and also prevented the shared_ptr member from being stomped on in the event you call getShared() and update() at the same time, and also kept it leak-free.



any thoughts?










share|improve this question









New contributor




MatkatMusic is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$












  • $begingroup$
    From C++20, there's std::atomic<shared_ptr<T>> partial specialization. You'll want to understand how it works if you're implementing your own.
    $endgroup$
    – Toby Speight
    9 hours ago
















1












1








1





$begingroup$


I am learning about one of the hardest parts of Audio development: the synchronization between the audio thread and the GUI thread. Per the discussion here https://forum.juce.com/t/timur-doumler-talks-on-c-audio-sharing-data-across-threads/26311 and here: https://stackoverflow.com/questions/15460829/lock-free-swap-of-two-unique-ptrt
I'm wondering if the following class solves the problem or comes close to solving it.



template<typename T>
struct SmartAtomicPtr
{
SmartAtomicPtr( T* newT )
{
update( newT );
}
~SmartAtomicPtr()
{
update(nullptr);
}
void update( T* newT, std::memory_order ord = memory_order_seq_cst )
{
keepAlive.reset( atomicTptr.exchange( newT, ord ) );
}
std::shared_ptr<T> getShared(std::memory_order ord = memory_order_seq_cst)
{
return std::make_shared<T>( atomicTptr.load(ord) );
}
T* getRaw(std::memory_order ord = memory_order_seq_cst)
{
return atomicTptr.load(ord);
}
private:
std::atomic<T*> atomicTptr{nullptr};
std::shared_ptr<T> keepAlive;
};


I know that whatever value ends up in the shared_ptr won't be deleted until the SmartAtomicPtr goes out of scope, which is fine.



the ultimate goal would be a lock-free, wait-free solution.



an example of where this might get used is the following interleaving of the audio and message thread. The goal is to keep the returned object from dangling



/*
AudioProcessor owns a SmartAtomicPtr<T> ptr that the message
thread has public access to.
*/
/* audio thread */ auto* t = ptr.getRaw();
/* message thread */ processor.ptr.update( new T() );
/* audio thread */ t->doSomething(); //t is a dangling pointer now


with getShared(), I believe that t no longer dangles:



/* audio thread */ auto t = ptr.getShared();
/* message thread */ processor.ptr.update( new T() );
/* audio thread */ t->doSomething(); //t is one of 2 shared_ptrs
//holding the previous atomic value of ptr


I ran into some double-deletes, but I believe I have solved them, and also prevented the shared_ptr member from being stomped on in the event you call getShared() and update() at the same time, and also kept it leak-free.



any thoughts?










share|improve this question









New contributor




MatkatMusic is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$




I am learning about one of the hardest parts of Audio development: the synchronization between the audio thread and the GUI thread. Per the discussion here https://forum.juce.com/t/timur-doumler-talks-on-c-audio-sharing-data-across-threads/26311 and here: https://stackoverflow.com/questions/15460829/lock-free-swap-of-two-unique-ptrt
I'm wondering if the following class solves the problem or comes close to solving it.



template<typename T>
struct SmartAtomicPtr
{
SmartAtomicPtr( T* newT )
{
update( newT );
}
~SmartAtomicPtr()
{
update(nullptr);
}
void update( T* newT, std::memory_order ord = memory_order_seq_cst )
{
keepAlive.reset( atomicTptr.exchange( newT, ord ) );
}
std::shared_ptr<T> getShared(std::memory_order ord = memory_order_seq_cst)
{
return std::make_shared<T>( atomicTptr.load(ord) );
}
T* getRaw(std::memory_order ord = memory_order_seq_cst)
{
return atomicTptr.load(ord);
}
private:
std::atomic<T*> atomicTptr{nullptr};
std::shared_ptr<T> keepAlive;
};


I know that whatever value ends up in the shared_ptr won't be deleted until the SmartAtomicPtr goes out of scope, which is fine.



the ultimate goal would be a lock-free, wait-free solution.



an example of where this might get used is the following interleaving of the audio and message thread. The goal is to keep the returned object from dangling



/*
AudioProcessor owns a SmartAtomicPtr<T> ptr that the message
thread has public access to.
*/
/* audio thread */ auto* t = ptr.getRaw();
/* message thread */ processor.ptr.update( new T() );
/* audio thread */ t->doSomething(); //t is a dangling pointer now


with getShared(), I believe that t no longer dangles:



/* audio thread */ auto t = ptr.getShared();
/* message thread */ processor.ptr.update( new T() );
/* audio thread */ t->doSomething(); //t is one of 2 shared_ptrs
//holding the previous atomic value of ptr


I ran into some double-deletes, but I believe I have solved them, and also prevented the shared_ptr member from being stomped on in the event you call getShared() and update() at the same time, and also kept it leak-free.



any thoughts?







c++ pointers audio lock-free atomic






share|improve this question









New contributor




MatkatMusic is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




MatkatMusic is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited 8 mins ago









200_success

130k16153417




130k16153417






New contributor




MatkatMusic is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked 13 hours ago









MatkatMusicMatkatMusic

82




82




New contributor




MatkatMusic is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





MatkatMusic is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






MatkatMusic is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.












  • $begingroup$
    From C++20, there's std::atomic<shared_ptr<T>> partial specialization. You'll want to understand how it works if you're implementing your own.
    $endgroup$
    – Toby Speight
    9 hours ago




















  • $begingroup$
    From C++20, there's std::atomic<shared_ptr<T>> partial specialization. You'll want to understand how it works if you're implementing your own.
    $endgroup$
    – Toby Speight
    9 hours ago


















$begingroup$
From C++20, there's std::atomic<shared_ptr<T>> partial specialization. You'll want to understand how it works if you're implementing your own.
$endgroup$
– Toby Speight
9 hours ago






$begingroup$
From C++20, there's std::atomic<shared_ptr<T>> partial specialization. You'll want to understand how it works if you're implementing your own.
$endgroup$
– Toby Speight
9 hours ago












1 Answer
1






active

oldest

votes


















1












$begingroup$

keepAlive.reset is not thread safe. So your class as a whole cannot be thread safe.






share|improve this answer









$endgroup$













  • $begingroup$
    Concrete proof that a short answer can be a great answer - good one!
    $endgroup$
    – Toby Speight
    9 hours ago











Your Answer





StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");

StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});






MatkatMusic is a new contributor. Be nice, and check out our Code of Conduct.










draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214829%2fpassing-objects-atomically-across-threads-without-locks-or-data-races-for-audio%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1












$begingroup$

keepAlive.reset is not thread safe. So your class as a whole cannot be thread safe.






share|improve this answer









$endgroup$













  • $begingroup$
    Concrete proof that a short answer can be a great answer - good one!
    $endgroup$
    – Toby Speight
    9 hours ago
















1












$begingroup$

keepAlive.reset is not thread safe. So your class as a whole cannot be thread safe.






share|improve this answer









$endgroup$













  • $begingroup$
    Concrete proof that a short answer can be a great answer - good one!
    $endgroup$
    – Toby Speight
    9 hours ago














1












1








1





$begingroup$

keepAlive.reset is not thread safe. So your class as a whole cannot be thread safe.






share|improve this answer









$endgroup$



keepAlive.reset is not thread safe. So your class as a whole cannot be thread safe.







share|improve this answer












share|improve this answer



share|improve this answer










answered 11 hours ago









ratchet freakratchet freak

12k1344




12k1344












  • $begingroup$
    Concrete proof that a short answer can be a great answer - good one!
    $endgroup$
    – Toby Speight
    9 hours ago


















  • $begingroup$
    Concrete proof that a short answer can be a great answer - good one!
    $endgroup$
    – Toby Speight
    9 hours ago
















$begingroup$
Concrete proof that a short answer can be a great answer - good one!
$endgroup$
– Toby Speight
9 hours ago




$begingroup$
Concrete proof that a short answer can be a great answer - good one!
$endgroup$
– Toby Speight
9 hours ago










MatkatMusic is a new contributor. Be nice, and check out our Code of Conduct.










draft saved

draft discarded


















MatkatMusic is a new contributor. Be nice, and check out our Code of Conduct.













MatkatMusic is a new contributor. Be nice, and check out our Code of Conduct.












MatkatMusic is a new contributor. Be nice, and check out our Code of Conduct.
















Thanks for contributing an answer to Code Review Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


Use MathJax to format equations. MathJax reference.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214829%2fpassing-objects-atomically-across-threads-without-locks-or-data-races-for-audio%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Webac Holding Inhaltsverzeichnis Geschichte | Organisationsstruktur | Tochterfirmen |...

What's the meaning of a knight fighting a snail in medieval book illustrations?What is the meaning of a glove...

Salamanca Inhaltsverzeichnis Lage und Klima | Bevölkerungsentwicklung | Geschichte | Kultur und...