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