Add fallible accessors to ThreadLocal.
#39
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Problem
I'm working on a custom global allocator that tracks allocation and deallocation events for the purpose of tracking memory consumption/usage and attributing it to different components. As such, for fast/uncontended access to update the statistics of a particular component, I use
ThreadLocalto hold the necessary data structures, and then scatter/gather them in a background thread.Since the allocator is intercepting all allocations and deallocations, this means that when TLS destructors are run for
ThreadLocalitself, specificallyTHREAD_HOLDER, it triggers calls into my custom allocator, which result in hitting the normal "get the statistics for the given component" logic, which tries to access theThreadLocal... and ends up panicking due to the access after destruction.The custom allocator already tries to avoid reentrantly tracking (de)allocations but since the TLS destructor is the root of the stack, as it were, and there's no way that I know of to check that the key is in fact destroyed, I can't detect what's happening out-of-band, and need the access to
THREAD_HOLDERto be able to bubble that up.Solution
I've added fallible variants of all of the accessor methods:
try_get,try_get_or,try_get_or_try, andtry_get_or_default. They simply call out tothread::try_get, which is itself a fallible variant ofthread::get. Ultimately, we're just bubbling up the already-availableAccessError.Testing
I added two tests for ensuring the fallible
try_*variants work, but I was struggling to conceive a unit test that represented my particular example, given the need for a custom allocator to be in place to affectTHREAD_HOLDERin the necessary way, and to that end... I wonder if it even necessarily matters: we're really just surfacing existingLocalKeymethods.