mirror of
https://github.com/wolfpld/tracy.git
synced 2025-03-20 07:40:02 +08:00
Only recycle producers, if there's no data in queue.
("The queue" is per-thread partial queue here.)
This fixes a problem where one thread writes to the queue, then is
terminated, making the (partially filled) queue available for other
threads to recycle. If another thread re-owns the queue, it will change
the associated thread id, while part of the queue was filled by the
original thread. This obviously created invalid data during dequeue.
The fix makes the recycling process check not only for queue inactivity
(which is marked when the original thread terminates), but also if the
queue is empty, preventing mixing data from different threads.
This commit is contained in:
parent
1c0c6311ec
commit
7a6564feae
@ -2051,23 +2051,26 @@ private:
|
||||
return recycle_or_create_producer(recycled);
|
||||
}
|
||||
|
||||
ProducerBase* recycle_or_create_producer(bool& recycled)
|
||||
{
|
||||
// Try to re-use one first
|
||||
for (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) {
|
||||
if (ptr->inactive.load(std::memory_order_relaxed)) {
|
||||
bool expected = true;
|
||||
if (ptr->inactive.compare_exchange_strong(expected, /* desired */ false, std::memory_order_acquire, std::memory_order_relaxed)) {
|
||||
// We caught one! It's been marked as activated, the caller can have it
|
||||
recycled = true;
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recycled = false;
|
||||
return add_producer(static_cast<ProducerBase*>(create<ExplicitProducer>(this)));
|
||||
}
|
||||
ProducerBase* recycle_or_create_producer(bool& recycled)
|
||||
{
|
||||
// Try to re-use one first
|
||||
for (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) {
|
||||
if (ptr->inactive.load(std::memory_order_relaxed)) {
|
||||
if( ptr->size_approx() == 0 )
|
||||
{
|
||||
bool expected = true;
|
||||
if (ptr->inactive.compare_exchange_strong(expected, /* desired */ false, std::memory_order_acquire, std::memory_order_relaxed)) {
|
||||
// We caught one! It's been marked as activated, the caller can have it
|
||||
recycled = true;
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recycled = false;
|
||||
return add_producer(static_cast<ProducerBase*>(create<ExplicitProducer>(this)));
|
||||
}
|
||||
|
||||
ProducerBase* add_producer(ProducerBase* producer)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user