/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * 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. */ /** * Improved thread local storage for non-trivial types (similar speed as * pthread_getspecific but only consumes a single pthread_key_t, and 4x faster * than boost::thread_specific_ptr). * * ThreadLocal objects can be grouped together logically under a tag. Within * a tag, each object has a unique id. The combination of tag and id is used to * locate the managed object corresponding to the current thread. * * Also includes an accessor interface to iterate all of the managed * objects owned by a ThreadLocal object, each corresponding to a * separate thread. accessAllThreads() initializes an accessor * which holds * a lock *that blocks all creation and destruction of managed * objects managed by the ThreadLocal. The accessor can be used * as an iterable container. Note: for now, the accessor also happens to hold * other per tag global locks and hence calls to accessAllThreads() are * serialized at tag level. * * accessAllThreads() can race with destruction of thread-local elements. We * provide a strict mode which is dangerous because it requires the access lock * to be held while destroying thread-local elements which could cause * deadlocks. We gate this mode behind the AccessModeStrict template parameter. * * Intended use is for frequent write, infrequent read data access patterns such * as counters. * * There are two classes here - ThreadLocal and ThreadLocalPtr. ThreadLocalPtr * has semantics similar to boost::thread_specific_ptr. ThreadLocal is a thin * wrapper around ThreadLocalPtr that manages allocation automatically. */ #pragma once #include <iterator> #include <thread> #include <type_traits> #include <utility> #include <folly/Likely.h> #include <folly/Portability.h> #include <folly/ScopeGuard.h> #include <folly/SharedMutex.h> #include <folly/detail/ThreadLocalDetail.h> namespace folly { template <class T, class Tag, class AccessMode> class ThreadLocalPtr; template <class T, class Tag = void, class AccessMode = void> class ThreadLocal { … }; /* * The idea here is that __thread is faster than pthread_getspecific, so we * keep a __thread array of pointers to objects (ThreadEntry::elements) where * each array has an index for each unique instance of the ThreadLocalPtr * object. Each ThreadLocalPtr object has a unique id that is an index into * these arrays so we can fetch the correct object from thread local storage * very efficiently. * * In order to prevent unbounded growth of the id space and thus huge * ThreadEntry::elements, arrays, for example due to continuous creation and * destruction of ThreadLocalPtr objects, we keep a set of all active * instances. When an instance is destroyed we remove it from the active * set and insert the id into freeIds_ for reuse. These operations require a * global mutex, but only happen at construction and destruction time. * * We use a single global pthread_key_t per Tag to manage object destruction and * memory cleanup upon thread exit because there is a finite number of * pthread_key_t's available per machine. * * NOTE: Apple platforms don't support the same semantics for __thread that * Linux does (and it's only supported at all on i386). For these, use * pthread_setspecific()/pthread_getspecific() for the per-thread * storage. Windows (MSVC and GCC) does support the same semantics * with __declspec(thread) */ template <class T, class Tag = void, class AccessMode = void> class ThreadLocalPtr { … }; } // namespace folly