1 // Copyright (C) 2014 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 
17 #include "android/base/Compiler.h"
18 
19 #ifdef _WIN32
20 #  define WIN32_LEAN_AND_MEAN 1
21 #  include <windows.h>
22 #else
23 #  include <pthread.h>
24 #endif
25 
26 namespace android {
27 namespace base {
28 namespace guest {
29 
30 // A class to model storage of thread-specific values, that can be
31 // destroyed on thread exit.
32 //
33 // Note that on Windows, a thread must call OnThreadExit() explicitly
34 // here to ensure that the values are probably discarded. This is an
35 // unfortunate requirement of the Win32 API, which doesn't support
36 // destructors at all.
37 //
38 // There are various hacks on the web to try to achieve this automatically
39 // (e.g. [1]) but they rely on using the Microsoft build tools,
40 // which doesn't work for us.
41 //
42 // Note another important issue with ThreadStore instances: if you create
43 // one instance in a shared library, you need to make sure that it is
44 // always destroyed before the library is unloaded. Otherwise, future
45 // thread exit will likely crash, due to calling a destructor function
46 // that is no longer in the process' address space.
47 //
48 // Finally, destroying an instance does _not_ free the corresponding values,
49 // because doing so properly requires coordinating all participating threads,
50 // which is impossible to achieve in the most general case. Thus, consider
51 // that thread-local values are always leaked on library unload, or on
52 // program exit.
53 //
54 // [1] http://stackoverflow.com/questions/14538159/about-tls-callback-in-windows
55 
56 // ThreadStoreBase is the base class used by all ThreadStore template
57 // instances, used to reduce bloat.
58 class ThreadStoreBase {
59 public:
60     // Type of a function used to destroy a thread-specific value that
61     // was previously assigned by calling set().
62     typedef void (Destructor)(void* value);
63 
64     // Initialize instance so that is hold keys that must be destroyed
65     // on thread exit by calling |destroy|.
66     explicit ThreadStoreBase(Destructor* destroy);
67 
68     // NOTE: Destructor don't free the thread-local values, but are required
69     // to avoid crashes (see note above).
70     ~ThreadStoreBase();
71 
72     // Retrieve current thread-specific value from store.
73 #ifdef _WIN32
74     void* get() const;
75 #else
get()76     inline void* get() const {
77         return pthread_getspecific(mKey);
78     }
79 #endif
80 
81     // Set the new thread-specific value.
82 #ifdef _WIN32
83     void set(void* value);
84 #else
set(void * value)85     inline void set(void* value) {
86         pthread_setspecific(mKey, value);
87     }
88 #endif
89 
swap(void * value)90     inline void* swap(void* value) {
91         void* old = get();
92         set(value);
93         return old;
94     }
95 
96 #ifdef _WIN32
97     // Each thread should call this function on exit to ensure that
98     // all corresponding TLS values are properly freed.
99     static void OnThreadExit();
100 #else
101     // Nothing to do on Posix.
OnThreadExit()102     static inline void OnThreadExit() {}
103 #endif
104 
105 private:
106     // Ensure you can't create an empty ThreadStore instance.
107     ThreadStoreBase();
108 
109     DISALLOW_COPY_AND_ASSIGN(ThreadStoreBase);
110 
111 #ifdef _WIN32
112     int mKey;
113 #else
114     pthread_key_t mKey;
115 #endif
116 };
117 
118 // ThreadStore is a template class used to implement a thread-local store
119 // of objects of type |T|. Note that the store owns the objects, and these
120 // are destroyed when an android::base::Thread exits.
121 template <typename T>
122 class ThreadStore : public ThreadStoreBase {
123 public:
124     // Create a new ThreadStore instance.
ThreadStore()125     ThreadStore() : ThreadStoreBase(myDestructor) {}
126 
127     // Retrieve the thread-specific object instance, or NULL if set()
128     // was never called before in the current thread.
get()129     T* get() {
130         return static_cast<T*>(ThreadStoreBase::get());
131     }
132 
133     // Set the current thread-specific objet instance for this thread.
134     // |t| is the new object instance.
135     // NOTE: Any previous object instance is deleted.
set(T * t)136     void set(T* t) {
137         T* old = static_cast<T*>(swap(t));
138         delete old;
139     }
140 
141     // Swap the current thread-specific object for this thread.
142     // |t| is the new object instance.
143     // Return the previous one. Transfers ownership to the caller.
swap(T * t)144     T* swap(T* t) {
145         return static_cast<T*>(ThreadStoreBase::swap(t));
146     }
147 
148 private:
myDestructor(void * opaque)149     static void myDestructor(void* opaque) {
150         delete static_cast<T*>(opaque);
151     }
152 };
153 
154 }  // namespace guest
155 }  // namespace base
156 }  // namespace android
157