Fix data race in freeing control block
This commit is contained in:
@@ -172,19 +172,24 @@ private:
|
||||
*/
|
||||
void release() noexcept {
|
||||
if (control_block) {
|
||||
// Prevent weak count from going to 0 concurrently
|
||||
control_block->increment_weak();
|
||||
|
||||
uint32_t prev_strong = control_block->decrement_strong();
|
||||
|
||||
// If this was the last strong reference, destroy the object
|
||||
if (prev_strong == 1) {
|
||||
T *obj = get();
|
||||
obj->~T();
|
||||
}
|
||||
|
||||
// Check if there are any weak references
|
||||
uint32_t current_weak =
|
||||
control_block->weak_count.load(std::memory_order_acquire);
|
||||
if (current_weak == 0) {
|
||||
std::free(control_block);
|
||||
}
|
||||
// Now release our temporary weak reference
|
||||
uint32_t prev_weak = control_block->decrement_weak();
|
||||
|
||||
// If this was the last weak reference and we destroyed the object,
|
||||
// we can free the control block
|
||||
if (prev_weak == 1 && prev_strong == 1) {
|
||||
std::free(control_block);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -314,16 +319,14 @@ private:
|
||||
*/
|
||||
void release() noexcept {
|
||||
if (control_block) {
|
||||
// Prevent strong count from going to 0 concurrently
|
||||
auto strong = lock();
|
||||
uint32_t prev_weak = control_block->decrement_weak();
|
||||
|
||||
// If this was the last weak reference, check if we need to free control
|
||||
// block
|
||||
if (prev_weak == 1) {
|
||||
uint32_t current_strong =
|
||||
control_block->strong_count.load(std::memory_order_acquire);
|
||||
if (current_strong == 0) {
|
||||
std::free(control_block);
|
||||
}
|
||||
if (prev_weak == 1 && !strong) {
|
||||
std::free(control_block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user