123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- // Copyright 2019 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #ifndef BASE_THREADING_THREAD_LOCAL_INTERNAL_H_
- #define BASE_THREADING_THREAD_LOCAL_INTERNAL_H_
- #if DCHECK_IS_ON()
- #include <atomic>
- #include <memory>
- #include <ostream>
- #include "base/macros.h"
- #include "base/threading/thread_local_storage.h"
- namespace base {
- namespace internal {
- // A version of ThreadLocalOwnedPointer which verifies that it's only destroyed
- // when no threads, other than the one it is destroyed on, have remaining state
- // set in it. A ThreadLocalOwnedPointer instance being destroyed too early would
- // result in leaks per unregistering the TLS slot (and thus the DeleteTlsPtr
- // hook).
- template <typename T>
- class CheckedThreadLocalOwnedPointer {
- public:
- CheckedThreadLocalOwnedPointer() = default;
- ~CheckedThreadLocalOwnedPointer() {
- Set(nullptr);
- DCHECK_EQ(num_assigned_threads_.load(std::memory_order_relaxed), 0)
- << "Memory leak: Must join all threads or release all associated "
- "thread-local slots before ~ThreadLocalOwnedPointer";
- }
- T* Get() const {
- PtrTracker* const ptr_tracker = static_cast<PtrTracker*>(slot_.Get());
- return ptr_tracker ? ptr_tracker->ptr_.get() : nullptr;
- }
- void Set(std::unique_ptr<T> ptr) {
- delete static_cast<PtrTracker*>(slot_.Get());
- if (ptr)
- slot_.Set(new PtrTracker(this, std::move(ptr)));
- else
- slot_.Set(nullptr);
- }
- private:
- struct PtrTracker {
- public:
- PtrTracker(CheckedThreadLocalOwnedPointer<T>* outer, std::unique_ptr<T> ptr)
- : outer_(outer), ptr_(std::move(ptr)) {
- outer_->num_assigned_threads_.fetch_add(1, std::memory_order_relaxed);
- }
- ~PtrTracker() {
- outer_->num_assigned_threads_.fetch_sub(1, std::memory_order_relaxed);
- }
- CheckedThreadLocalOwnedPointer<T>* const outer_;
- const std::unique_ptr<T> ptr_;
- };
- static void DeleteTlsPtr(void* ptr) { delete static_cast<PtrTracker*>(ptr); }
- ThreadLocalStorage::Slot slot_{&DeleteTlsPtr};
- std::atomic_int num_assigned_threads_{0};
- DISALLOW_COPY_AND_ASSIGN(CheckedThreadLocalOwnedPointer<T>);
- };
- } // namespace internal
- } // namespace base
- #endif // DCHECK_IS_ON()
- #endif // BASE_THREADING_THREAD_LOCAL_INTERNAL_H_
|