aboutsummaryrefslogtreecommitdiffstats
path: root/emulator/opengl/shared/emugl/common/thread_store.h
diff options
context:
space:
mode:
Diffstat (limited to 'emulator/opengl/shared/emugl/common/thread_store.h')
-rw-r--r--emulator/opengl/shared/emugl/common/thread_store.h110
1 files changed, 110 insertions, 0 deletions
diff --git a/emulator/opengl/shared/emugl/common/thread_store.h b/emulator/opengl/shared/emugl/common/thread_store.h
new file mode 100644
index 0000000..5fd08bd
--- /dev/null
+++ b/emulator/opengl/shared/emugl/common/thread_store.h
@@ -0,0 +1,110 @@
+// 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.
+
+#ifndef EMUGL_COMMON_THREAD_STORE_H
+#define EMUGL_COMMON_THREAD_STORE_H
+
+#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN 1
+# include <windows.h>
+#else
+# include <pthread.h>
+#endif
+
+namespace emugl {
+
+// 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
+
+class ThreadStore {
+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 ThreadStore(Destructor* destroy);
+
+ // NOTE: Destructor don't free the thread-local values, but are required
+ // to avoid crashes (see note above).
+ ~ThreadStore();
+
+ // 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
+
+#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, or simply
+ // copy it in any way.
+ ThreadStore();
+ ThreadStore(const ThreadStore&);
+ ThreadStore& operator=(const ThreadStore&);
+
+#ifdef _WIN32
+ int mKey;
+#else
+ pthread_key_t mKey;
+#endif
+};
+
+} // namespace emugl
+
+#endif // EMUGL_COMMON_THREAD_STORE_H