1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef BASE_THREAD_LOCAL_STORAGE_H_ 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define BASE_THREAD_LOCAL_STORAGE_H_ 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/basictypes.h" 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_POSIX) 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <pthread.h> 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Wrapper for thread local storage. This class doesn't do much except provide 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// an API for portability. 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ThreadLocalStorage { 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Prototype for the TLS destructor function, which can be optionally used to 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // cleanup thread local storage on thread exit. 'value' is the data that is 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // stored in thread local storage. 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott typedef void (*TLSDestructorFunc)(void* value); 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // A key representing one value stored in TLS. 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott class Slot { 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit Slot(TLSDestructorFunc destructor = NULL); 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This constructor should be used for statics. 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // It returns an uninitialized Slot. 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit Slot(base::LinkerInitialized x) {} 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Set up the TLS slot. Called by the constructor. 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 'destructor' is a pointer to a function to perform per-thread cleanup of 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // this object. If set to NULL, no cleanup is done for this TLS slot. 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Returns false on error. 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool Initialize(TLSDestructorFunc destructor); 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Free a previously allocated TLS 'slot'. 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If a destructor was set for this slot, removes 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the destructor so that remaining threads exiting 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // will not free data. 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void Free(); 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Get the thread-local value stored in slot 'slot'. 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Values are guaranteed to initially be zero. 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void* Get() const; 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Set the thread-local value stored in slot 'slot' to 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // value 'value'. 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void Set(void* value); 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool initialized() const { return initialized_; } 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The internals of this struct should be considered private. 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool initialized_; 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN) 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int slot_; 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_POSIX) 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pthread_key_t key_; 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DISALLOW_COPY_AND_ASSIGN(Slot); 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott }; 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN) 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Function called when on thread exit to call TLS 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // destructor functions. This function is used internally. 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static void ThreadExit(); 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Function to lazily initialize our thread local storage. 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static void **Initialize(); 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The maximum number of 'slots' in our thread local storage stack. 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // For now, this is fixed. We could either increase statically, or 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // we could make it dynamic in the future. 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static const int kThreadLocalStorageSize = 64; 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static long tls_key_; 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static long tls_max_; 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static TLSDestructorFunc tls_destructors_[kThreadLocalStorageSize]; 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif // OS_WIN 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DISALLOW_COPY_AND_ASSIGN(ThreadLocalStorage); 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Temporary backwards-compatible name. 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// TODO(evanm): replace all usage of TLSSlot. 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttypedef ThreadLocalStorage::Slot TLSSlot; 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif // BASE_THREAD_LOCAL_STORAGE_H_ 95