Repo created
This commit is contained in:
parent
81b91f4139
commit
f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions
|
|
@ -0,0 +1,80 @@
|
|||
// 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 "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_
|
||||
Loading…
Add table
Add a link
Reference in a new issue