Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/ipc/chromium/src/base/thread_local.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
4
// Use of this source code is governed by a BSD-style license that can be
5
// found in the LICENSE file.
6
7
// WARNING: Thread local storage is a bit tricky to get right.  Please make
8
// sure that this is really the proper solution for what you're trying to
9
// achieve.  Don't prematurely optimize, most likely you can just use a Lock.
10
//
11
// These classes implement a warpper around the platform's TLS storage
12
// mechanism.  On construction, they will allocate a TLS slot, and free the
13
// TLS slot on destruction.  No memory management (creation or destruction) is
14
// handled.  This means for uses of ThreadLocalPointer, you must correctly
15
// manage the memory yourself, these classes will not destroy the pointer for
16
// you.  There are no at-thread-exit actions taken by these classes.
17
//
18
// ThreadLocalPointer<Type> wraps a Type*.  It performs no creation or
19
// destruction, so memory management must be handled elsewhere.  The first call
20
// to Get() on a thread will return NULL.  You can update the pointer with a
21
// call to Set().
22
//
23
// ThreadLocalBoolean wraps a bool.  It will default to false if it has never
24
// been set otherwise with Set().
25
//
26
// Thread Safety:  An instance of ThreadLocalStorage is completely thread safe
27
// once it has been created.  If you want to dynamically create an instance,
28
// you must of course properly deal with safety and race conditions.  This
29
// means a function-level static initializer is generally inappropiate.
30
//
31
// Example usage:
32
//   // My class is logically attached to a single thread.  We cache a pointer
33
//   // on the thread it was created on, so we can implement current().
34
//   MyClass::MyClass() {
35
//     DCHECK(Singleton<ThreadLocalPointer<MyClass> >::get()->Get() == NULL);
36
//     Singleton<ThreadLocalPointer<MyClass> >::get()->Set(this);
37
//   }
38
//
39
//   MyClass::~MyClass() {
40
//     DCHECK(Singleton<ThreadLocalPointer<MyClass> >::get()->Get() != NULL);
41
//     Singleton<ThreadLocalPointer<MyClass> >::get()->Set(NULL);
42
//   }
43
//
44
//   // Return the current MyClass associated with the calling thread, can be
45
//   // NULL if there isn't a MyClass associated.
46
//   MyClass* MyClass::current() {
47
//     return Singleton<ThreadLocalPointer<MyClass> >::get()->Get();
48
//   }
49
50
#ifndef BASE_THREAD_LOCAL_H_
51
#define BASE_THREAD_LOCAL_H_
52
53
#include "base/basictypes.h"
54
55
#if defined(OS_POSIX)
56
#include <pthread.h>
57
#endif
58
59
namespace base {
60
61
// Helper functions that abstract the cross-platform APIs.  Do not use directly.
62
struct ThreadLocalPlatform {
63
#if defined(OS_WIN)
64
  typedef int SlotType;
65
#elif defined(OS_POSIX)
66
  typedef pthread_key_t SlotType;
67
#endif
68
69
  static void AllocateSlot(SlotType& slot);
70
  static void FreeSlot(SlotType& slot);
71
  static void* GetValueFromSlot(SlotType& slot);
72
  static void SetValueInSlot(SlotType& slot, void* value);
73
};
74
75
template <typename Type>
76
class ThreadLocalPointer {
77
 public:
78
6
  ThreadLocalPointer() : slot_() {
79
6
    ThreadLocalPlatform::AllocateSlot(slot_);
80
6
  }
base::ThreadLocalPointer<MessageLoop>::ThreadLocalPointer()
Line
Count
Source
78
3
  ThreadLocalPointer() : slot_() {
79
3
    ThreadLocalPlatform::AllocateSlot(slot_);
80
3
  }
base::ThreadLocalPointer<void>::ThreadLocalPointer()
Line
Count
Source
78
3
  ThreadLocalPointer() : slot_() {
79
3
    ThreadLocalPlatform::AllocateSlot(slot_);
80
3
  }
81
82
6
  ~ThreadLocalPointer() {
83
6
    ThreadLocalPlatform::FreeSlot(slot_);
84
6
  }
base::ThreadLocalPointer<MessageLoop>::~ThreadLocalPointer()
Line
Count
Source
82
3
  ~ThreadLocalPointer() {
83
3
    ThreadLocalPlatform::FreeSlot(slot_);
84
3
  }
base::ThreadLocalPointer<void>::~ThreadLocalPointer()
Line
Count
Source
82
3
  ~ThreadLocalPointer() {
83
3
    ThreadLocalPlatform::FreeSlot(slot_);
84
3
  }
85
86
9
  Type* Get() {
87
9
    return static_cast<Type*>(ThreadLocalPlatform::GetValueFromSlot(slot_));
88
9
  }
base::ThreadLocalPointer<MessageLoop>::Get()
Line
Count
Source
86
9
  Type* Get() {
87
9
    return static_cast<Type*>(ThreadLocalPlatform::GetValueFromSlot(slot_));
88
9
  }
Unexecuted instantiation: base::ThreadLocalPointer<void>::Get()
89
90
22
  void Set(Type* ptr) {
91
22
    ThreadLocalPlatform::SetValueInSlot(slot_, ptr);
92
22
  }
base::ThreadLocalPointer<MessageLoop>::Set(MessageLoop*)
Line
Count
Source
90
19
  void Set(Type* ptr) {
91
19
    ThreadLocalPlatform::SetValueInSlot(slot_, ptr);
92
19
  }
base::ThreadLocalPointer<void>::Set(void*)
Line
Count
Source
90
3
  void Set(Type* ptr) {
91
3
    ThreadLocalPlatform::SetValueInSlot(slot_, ptr);
92
3
  }
93
94
 private:
95
  typedef ThreadLocalPlatform::SlotType SlotType;
96
97
  SlotType slot_;
98
99
  DISALLOW_COPY_AND_ASSIGN(ThreadLocalPointer<Type>);
100
};
101
102
class ThreadLocalBoolean {
103
 public:
104
3
  ThreadLocalBoolean() { }
105
3
  ~ThreadLocalBoolean() { }
106
107
0
  bool Get() {
108
0
    return tlp_.Get() != NULL;
109
0
  }
110
111
3
  void Set(bool val) {
112
3
    uintptr_t intVal = val ? 1 : 0;
113
3
    tlp_.Set(reinterpret_cast<void*>(intVal));
114
3
  }
115
116
 private:
117
  ThreadLocalPointer<void> tlp_;
118
119
  DISALLOW_COPY_AND_ASSIGN(ThreadLocalBoolean);
120
};
121
122
}  // namespace base
123
124
#endif  // BASE_THREAD_LOCAL_H_