// Copyright (C) 2014 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #pragma once #include "android/base/Compiler.h" #ifdef _WIN32 # define WIN32_LEAN_AND_MEAN 1 # include #else # include #endif namespace android { namespace base { namespace guest { // A class to model storage of thread-specific values, that can be // destroyed on thread exit. // // Note that on Windows, a thread must call OnThreadExit() explicitly // here to ensure that the values are probably discarded. This is an // unfortunate requirement of the Win32 API, which doesn't support // destructors at all. // // There are various hacks on the web to try to achieve this automatically // (e.g. [1]) but they rely on using the Microsoft build tools, // which doesn't work for us. // // Note another important issue with ThreadStore instances: if you create // one instance in a shared library, you need to make sure that it is // always destroyed before the library is unloaded. Otherwise, future // thread exit will likely crash, due to calling a destructor function // that is no longer in the process' address space. // // Finally, destroying an instance does _not_ free the corresponding values, // because doing so properly requires coordinating all participating threads, // which is impossible to achieve in the most general case. Thus, consider // that thread-local values are always leaked on library unload, or on // program exit. // // [1] http://stackoverflow.com/questions/14538159/about-tls-callback-in-windows // ThreadStoreBase is the base class used by all ThreadStore template // instances, used to reduce bloat. class ThreadStoreBase { public: // Type of a function used to destroy a thread-specific value that // was previously assigned by calling set(). typedef void (Destructor)(void* value); // Initialize instance so that is hold keys that must be destroyed // on thread exit by calling |destroy|. explicit ThreadStoreBase(Destructor* destroy); // NOTE: Destructor don't free the thread-local values, but are required // to avoid crashes (see note above). ~ThreadStoreBase(); // Retrieve current thread-specific value from store. #ifdef _WIN32 void* get() const; #else inline void* get() const { return pthread_getspecific(mKey); } #endif // Set the new thread-specific value. #ifdef _WIN32 void set(void* value); #else inline void set(void* value) { pthread_setspecific(mKey, value); } #endif inline void* swap(void* value) { void* old = get(); set(value); return old; } #ifdef _WIN32 // Each thread should call this function on exit to ensure that // all corresponding TLS values are properly freed. static void OnThreadExit(); #else // Nothing to do on Posix. static inline void OnThreadExit() {} #endif private: // Ensure you can't create an empty ThreadStore instance. ThreadStoreBase(); DISALLOW_COPY_AND_ASSIGN(ThreadStoreBase); #ifdef _WIN32 int mKey; #else pthread_key_t mKey; #endif }; // ThreadStore is a template class used to implement a thread-local store // of objects of type |T|. Note that the store owns the objects, and these // are destroyed when an android::base::Thread exits. template class ThreadStore : public ThreadStoreBase { public: // Create a new ThreadStore instance. ThreadStore() : ThreadStoreBase(myDestructor) {} // Retrieve the thread-specific object instance, or NULL if set() // was never called before in the current thread. T* get() { return static_cast(ThreadStoreBase::get()); } // Set the current thread-specific objet instance for this thread. // |t| is the new object instance. // NOTE: Any previous object instance is deleted. void set(T* t) { T* old = static_cast(swap(t)); delete old; } // Swap the current thread-specific object for this thread. // |t| is the new object instance. // Return the previous one. Transfers ownership to the caller. T* swap(T* t) { return static_cast(ThreadStoreBase::swap(t)); } private: static void myDestructor(void* opaque) { delete static_cast(opaque); } }; } // namespace guest } // namespace base } // namespace android