annotate win32-mingw/include/kj/threadlocal.h @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents eccd51b72864
children
rev   line source
Chris@64 1 // Copyright (c) 2014, Jason Choy <jjwchoy@gmail.com>
Chris@64 2 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
Chris@64 3 // Licensed under the MIT License:
Chris@64 4 //
Chris@64 5 // Permission is hereby granted, free of charge, to any person obtaining a copy
Chris@64 6 // of this software and associated documentation files (the "Software"), to deal
Chris@64 7 // in the Software without restriction, including without limitation the rights
Chris@64 8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Chris@64 9 // copies of the Software, and to permit persons to whom the Software is
Chris@64 10 // furnished to do so, subject to the following conditions:
Chris@64 11 //
Chris@64 12 // The above copyright notice and this permission notice shall be included in
Chris@64 13 // all copies or substantial portions of the Software.
Chris@64 14 //
Chris@64 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Chris@64 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Chris@64 17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Chris@64 18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Chris@64 19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Chris@64 20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
Chris@64 21 // THE SOFTWARE.
Chris@64 22
Chris@64 23 #ifndef KJ_THREADLOCAL_H_
Chris@64 24 #define KJ_THREADLOCAL_H_
Chris@64 25
Chris@64 26 #if defined(__GNUC__) && !KJ_HEADER_WARNINGS
Chris@64 27 #pragma GCC system_header
Chris@64 28 #endif
Chris@64 29 // This file declares a macro `KJ_THREADLOCAL_PTR` for declaring thread-local pointer-typed
Chris@64 30 // variables. Use like:
Chris@64 31 // KJ_THREADLOCAL_PTR(MyType) foo = nullptr;
Chris@64 32 // This is equivalent to:
Chris@64 33 // thread_local MyType* foo = nullptr;
Chris@64 34 // This can only be used at the global scope.
Chris@64 35 //
Chris@64 36 // AVOID USING THIS. Use of thread-locals is discouraged because they often have many of the same
Chris@64 37 // properties as singletons: http://www.object-oriented-security.org/lets-argue/singletons
Chris@64 38 //
Chris@64 39 // Also, thread-locals tend to be hostile to event-driven code, which can be particularly
Chris@64 40 // surprising when using fibers (all fibers in the same thread will share the same threadlocals,
Chris@64 41 // even though they do not share a stack).
Chris@64 42 //
Chris@64 43 // That said, thread-locals are sometimes needed for runtime logistics in the KJ framework. For
Chris@64 44 // example, the current exception callback and current EventLoop are stored as thread-local
Chris@64 45 // pointers. Since KJ only ever needs to store pointers, not values, we avoid the question of
Chris@64 46 // whether these values' destructors need to be run, and we avoid the need for heap allocation.
Chris@64 47
Chris@64 48 #include "common.h"
Chris@64 49
Chris@64 50 #if !defined(KJ_USE_PTHREAD_THREADLOCAL) && defined(__APPLE__)
Chris@64 51 #include "TargetConditionals.h"
Chris@64 52 #if TARGET_OS_IPHONE
Chris@64 53 // iOS apparently does not support __thread (nor C++11 thread_local).
Chris@64 54 #define KJ_USE_PTHREAD_TLS 1
Chris@64 55 #endif
Chris@64 56 #endif
Chris@64 57
Chris@64 58 #if KJ_USE_PTHREAD_TLS
Chris@64 59 #include <pthread.h>
Chris@64 60 #endif
Chris@64 61
Chris@64 62 namespace kj {
Chris@64 63
Chris@64 64 #if KJ_USE_PTHREAD_TLS
Chris@64 65 // If __thread is unavailable, we'll fall back to pthreads.
Chris@64 66
Chris@64 67 #define KJ_THREADLOCAL_PTR(type) \
Chris@64 68 namespace { struct KJ_UNIQUE_NAME(_kj_TlpTag); } \
Chris@64 69 static ::kj::_::ThreadLocalPtr< type, KJ_UNIQUE_NAME(_kj_TlpTag)>
Chris@64 70 // Hack: In order to ensure each thread-local results in a unique template instance, we declare
Chris@64 71 // a one-off dummy type to use as the second type parameter.
Chris@64 72
Chris@64 73 namespace _ { // private
Chris@64 74
Chris@64 75 template <typename T, typename>
Chris@64 76 class ThreadLocalPtr {
Chris@64 77 // Hacky type to emulate __thread T*. We need a separate instance of the ThreadLocalPtr template
Chris@64 78 // for every thread-local variable, because we don't want to require a global constructor, and in
Chris@64 79 // order to initialize the TLS on first use we need to use a local static variable (in getKey()).
Chris@64 80 // Each template instance will get a separate such local static variable, fulfilling our need.
Chris@64 81
Chris@64 82 public:
Chris@64 83 ThreadLocalPtr() = default;
Chris@64 84 constexpr ThreadLocalPtr(decltype(nullptr)) {}
Chris@64 85 // Allow initialization to nullptr without a global constructor.
Chris@64 86
Chris@64 87 inline ThreadLocalPtr& operator=(T* val) {
Chris@64 88 pthread_setspecific(getKey(), val);
Chris@64 89 return *this;
Chris@64 90 }
Chris@64 91
Chris@64 92 inline operator T*() const {
Chris@64 93 return get();
Chris@64 94 }
Chris@64 95
Chris@64 96 inline T& operator*() const {
Chris@64 97 return *get();
Chris@64 98 }
Chris@64 99
Chris@64 100 inline T* operator->() const {
Chris@64 101 return get();
Chris@64 102 }
Chris@64 103
Chris@64 104 private:
Chris@64 105 inline T* get() const {
Chris@64 106 return reinterpret_cast<T*>(pthread_getspecific(getKey()));
Chris@64 107 }
Chris@64 108
Chris@64 109 inline static pthread_key_t getKey() {
Chris@64 110 static pthread_key_t key = createKey();
Chris@64 111 return key;
Chris@64 112 }
Chris@64 113
Chris@64 114 static pthread_key_t createKey() {
Chris@64 115 pthread_key_t key;
Chris@64 116 pthread_key_create(&key, 0);
Chris@64 117 return key;
Chris@64 118 }
Chris@64 119 };
Chris@64 120
Chris@64 121 } // namespace _ (private)
Chris@64 122
Chris@64 123 #elif __GNUC__
Chris@64 124
Chris@64 125 #define KJ_THREADLOCAL_PTR(type) static __thread type*
Chris@64 126 // GCC's __thread is lighter-weight than thread_local and is good enough for our purposes.
Chris@64 127
Chris@64 128 #else
Chris@64 129
Chris@64 130 #define KJ_THREADLOCAL_PTR(type) static thread_local type*
Chris@64 131
Chris@64 132 #endif // KJ_USE_PTHREAD_TLS
Chris@64 133
Chris@64 134 } // namespace kj
Chris@64 135
Chris@64 136 #endif // KJ_THREADLOCAL_H_