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