Closed
Description
Hello, consider the following interleaving:
Subscription::poll
const int length = std::atomic_load(&m_imagesLength); // reads eg 5
Subscription::removeImage
std::atomic_store(&m_imagesLength, length - 1); // writes 4
std::atomic_store(&m_images, newArray); // writes pointer to array of length 4
Subscription::poll
Image *images = std::atomic_load(&m_images); // reads pointer to array of length 4
...
fragmentsRead += images[i].poll(fragmentHandler, fragmentLimit - fragmentsRead); // with length == 4, this is undefined behavior.
Does that make sense?
This would be simpler to reason about, and perhaps faster if there were only one write (say a pointer to a vector) required for the conductor to communicate the updated set of images. So conductor would do:
// <updates m_conductorImageList>
delete m_latestImagesList.exchange(new std::vector<Image>(m_conductorImageList));
and subscriber does
if (m_latestImagesList.load(std::memory_order_relaxed) // rarely true
{
std::unique_ptr<std::vector<Images>> latest(m_latestImagesList.exchange(nullptr));
m_subscriberImagesList = *latest;
}
<uses m_subscriberImagesList>
Of course, any change that fixes the bug is good for me!
Thanks!