Skip to content

Commit

Permalink
Update destructor to allow deleting thread slots from workers
Browse files Browse the repository at this point in the history
  • Loading branch information
ashishb-solo committed Aug 1, 2024
1 parent a7fbe6d commit 6f8a9d3
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 1 deletion.
26 changes: 26 additions & 0 deletions source/common/thread_local/thread_local_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,32 @@ SlotPtr InstanceImpl::allocateSlot() {
InstanceImpl::SlotImpl::SlotImpl(InstanceImpl& parent, uint32_t index)
: parent_(parent), index_(index), still_alive_guard_(std::make_shared<bool>(true)) {}

InstanceImpl::SlotImpl::~SlotImpl() {
// Do nothing if the parent is already shutdown. Return early here to avoid accessing the main
// thread dispatcher because it may have been destroyed.
if (isShutdown()) {
return;
}

auto* main_thread_dispatcher = parent_.main_thread_dispatcher_;
// Main thread dispatcher may be nullptr if the slot is being created and destroyed during
// server initialization.
if (main_thread_dispatcher == nullptr || main_thread_dispatcher->isThreadSafe()) {
// If the slot is being destroyed on the main thread, we can remove it immediately.
parent_.removeSlot(index_);
} else {
// If the slot is being destroyed on a worker thread, we need to post the removal to the
// main thread. There are two possible cases here:
// 1. The removal is executed on the main thread as expected if the main dispatcher is still
// active. This is the common case and the clean up will be done as expected because the
// the worker dispatchers must be active before the main dispatcher is exited.
// 2. The removal is not executed if the main dispatcher has already exited. This is fine
// because the removal has no side effect and will be ignored. The shutdown process will
// clean up all the slots anyway.
main_thread_dispatcher->post([i = index_, &tls = parent_] { tls.removeSlot(i); });
}
}

std::function<void()> InstanceImpl::SlotImpl::wrapCallback(const std::function<void()>& cb) {
// See the header file comments for still_alive_guard_ for the purpose of this capture and the
// expired check below.
Expand Down
2 changes: 1 addition & 1 deletion source/common/thread_local/thread_local_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class InstanceImpl : Logger::Loggable<Logger::Id::main>, public NonCopyable, pub
// slot as callbacks drain from workers.
struct SlotImpl : public Slot {
SlotImpl(InstanceImpl& parent, uint32_t index);
~SlotImpl() override { parent_.removeSlot(index_); }
~SlotImpl() override;
std::function<void()> wrapCallback(const std::function<void()>& cb);
std::function<void()> dataCallback(const UpdateCb& cb);
static bool currentThreadRegisteredWorker(uint32_t index);
Expand Down

0 comments on commit 6f8a9d3

Please sign in to comment.