// SPDX-License-Identifier: AGPL-1.0-only // Copyright (C) 2018 Ludvig Strigeus . All Rights Reserved. #include "stdafx.h" #include "tunsafe_threading.h" #include MultithreadedDelayedDelete::MultithreadedDelayedDelete() { table_ = NULL; num_threads_ = 0; } MultithreadedDelayedDelete::~MultithreadedDelayedDelete() { assert(curr_.size() == 0); assert(next_.size() == 0); assert(to_delete_.size() == 0); free(table_); } void MultithreadedDelayedDelete::Configure(uint32 num_threads) { assert(table_ == NULL); num_threads_ = num_threads; table_ = (CheckpointData*)calloc(sizeof(CheckpointData), num_threads); } void MultithreadedDelayedDelete::Add(DoDeleteFunc *func, void *param) { if (num_threads_ == 0) { func(param); return; } lock_.Acquire(); Entry e = {func, param}; curr_.push_back(e); lock_.Release(); } void MultithreadedDelayedDelete::Checkpoint(uint32 thread_id) { table_[thread_id].value.store(1); } void MultithreadedDelayedDelete::MainCheckpoint() { // Wait for all threads to signal that they reached the checkpoint for (size_t i = 0; i < num_threads_; i++) { if (table_[i].value.load() == 0) return; } // All threads reached the checkpoint, clear the values for (size_t i = 0; i < num_threads_; i++) table_[i].value.store(0); // Swap curr and next, and delete all nexts. lock_.Acquire(); std::swap(curr_, next_); std::swap(curr_, to_delete_); lock_.Release(); for (auto it = to_delete_.begin(); it != to_delete_.end(); ++it) { it->func(it->param); } to_delete_.clear(); }