/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_ |