File: thread_local.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (71 lines) | stat: -rw-r--r-- 2,541 bytes parent folder | download | duplicates (11)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// Copyright 2011 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// WARNING: Thread local storage is a bit tricky to get right. Please make sure
// that this is really the proper solution for what you're trying to achieve.
// Don't prematurely optimize, most likely you can just use a Lock.

#ifndef BASE_THREADING_THREAD_LOCAL_H_
#define BASE_THREADING_THREAD_LOCAL_H_

#include <memory>

#include "base/dcheck_is_on.h"
#include "base/memory/ptr_util.h"
#include "base/threading/thread_local_internal.h"
#include "base/threading/thread_local_storage.h"

namespace base {

// `thread_local` is only allowed for trivially-destructible types (see
// //styleguide/c++/c++.md#thread_local-variables). This class provides
// thread-scoped management of non-trivially-destructible types. Pointers handed
// to it are owned and automatically deleted during their associated thread's
// exit phase (or when replaced if Set() is invoked multiple times on the same
// thread).
//
// The ThreadLocalOwnedPointer instance itself can only be destroyed when no
// threads, other than the one it is destroyed on, have remaining state set in
// it. Typically this means that ThreadLocalOwnedPointer instances are held in
// static storage or at the very least only recycled in the single-threaded
// phase between tests in the same process.
#if DCHECK_IS_ON()
template <typename T>
using ThreadLocalOwnedPointer = internal::CheckedThreadLocalOwnedPointer<T>;
#else   // DCHECK_IS_ON()
template <typename T>
class ThreadLocalOwnedPointer {
 public:
  ThreadLocalOwnedPointer() = default;

  ThreadLocalOwnedPointer(const ThreadLocalOwnedPointer&) = delete;
  ThreadLocalOwnedPointer& operator=(const ThreadLocalOwnedPointer&) = delete;

  ~ThreadLocalOwnedPointer() {
    // Assume that this thread is the only one with potential state left. This
    // is verified in ~CheckedThreadLocalOwnedPointer().
    Set(nullptr);
  }

  T* Get() const { return static_cast<T*>(slot_.Get()); }

  // Sets a new value, returns the old.
  std::unique_ptr<T> Set(std::unique_ptr<T> ptr) {
    auto existing = WrapUnique(Get());
    slot_.Set(const_cast<void*>(static_cast<const void*>(ptr.release())));
    return existing;
  }

  T& operator*() { return *Get(); }

 private:
  static void DeleteTlsPtr(void* ptr) { delete static_cast<T*>(ptr); }

  ThreadLocalStorage::Slot slot_{&DeleteTlsPtr};
};
#endif  // DCHECK_IS_ON()

}  // namespace base

#endif  // BASE_THREADING_THREAD_LOCAL_H_