18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2008 Apple Inc. All rights reserved. 3635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Copyright (C) 2009 Jian Li <jianli@chromium.org> 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met: 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer. 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * documentation and/or other materials provided with the distribution. 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * its contributors may be used to endorse or promote products derived 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * from this software without specific prior written permission. 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 30635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project/* Thread local storage is implemented by using either pthread API or Windows 31635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * native API. There is subtle semantic discrepancy for the cleanup function 32635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * implementation as noted below: 33635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * @ In pthread implementation, the destructor function will be called 34635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * repeatedly if there is still non-NULL value associated with the function. 35635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * @ In Windows native implementation, the destructor function will be called 36635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * only once. 37635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * This semantic discrepancy does not impose any problem because nowhere in 38635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * WebKit the repeated call bahavior is utilized. 39635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project */ 40635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef WTF_ThreadSpecific_h 428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define WTF_ThreadSpecific_h 438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/Noncopyable.h> 458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 46635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#if USE(PTHREADS) 478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <pthread.h> 485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#elif PLATFORM(QT) 495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include <QThreadStorage> 5006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#elif PLATFORM(GTK) 5106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#include <glib.h> 52d0825bca7fe65beaee391d30da42e937db621564Steve Block#elif OS(WINDOWS) 53635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <windows.h> 548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WTF { 578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#if !USE(PTHREADS) && !PLATFORM(QT) && !PLATFORM(GTK) && OS(WINDOWS) 59635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project// ThreadSpecificThreadExit should be called each time when a thread is detached. 60635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project// This is done automatically for threads created with WTF::createThread. 61635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid ThreadSpecificThreadExit(); 62635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 63635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 64ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdochtemplate<typename T> class ThreadSpecific { 65ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch WTF_MAKE_NONCOPYABLE(ThreadSpecific); 668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectpublic: 678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ThreadSpecific(); 688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project T* operator->(); 698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project operator T*(); 708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project T& operator*(); 718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectprivate: 7306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#if !USE(PTHREADS) && !PLATFORM(QT) && !PLATFORM(GTK) && OS(WINDOWS) 74635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project friend void ThreadSpecificThreadExit(); 75635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 765ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen 775ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen // Not implemented. It's technically possible to destroy a thread specific key, but one would need 785ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen // to make sure that all values have been destroyed already (usually, that all threads that used it 795ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen // have exited). It's unlikely that any user of this call will be in that situation - and having 805ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen // a destructor defined can be confusing, given that it has such strong pre-requisites to work correctly. 815ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen ~ThreadSpecific(); 82635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project T* get(); 848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project void set(T*); 858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project void static destroy(void* ptr); 868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 8706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#if USE(PTHREADS) || PLATFORM(QT) || PLATFORM(GTK) || OS(WINDOWS) 88ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch struct Data { 89ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch WTF_MAKE_NONCOPYABLE(Data); 90ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch public: 918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {} 92231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#if PLATFORM(QT) 93231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ~Data() { owner->destroy(this); } 94231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif 958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project T* value; 978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ThreadSpecific<T>* owner; 9806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#if !USE(PTHREADS) && !PLATFORM(QT) && !PLATFORM(GTK) 99635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project void (*destructor)(void*); 100635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project }; 102635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 104d0825bca7fe65beaee391d30da42e937db621564Steve Block#if ENABLE(SINGLE_THREADED) 105d0825bca7fe65beaee391d30da42e937db621564Steve Block T* m_value; 106d0825bca7fe65beaee391d30da42e937db621564Steve Block#else 107635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#if USE(PTHREADS) 1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pthread_key_t m_key; 1095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#elif PLATFORM(QT) 1105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian QThreadStorage<Data*> m_key; 11106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#elif PLATFORM(GTK) 11206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen GStaticPrivate m_key; 113d0825bca7fe65beaee391d30da42e937db621564Steve Block#elif OS(WINDOWS) 114635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int m_index; 1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 116d0825bca7fe65beaee391d30da42e937db621564Steve Block#endif 1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}; 1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 119d0825bca7fe65beaee391d30da42e937db621564Steve Block#if ENABLE(SINGLE_THREADED) 120d0825bca7fe65beaee391d30da42e937db621564Steve Blocktemplate<typename T> 121d0825bca7fe65beaee391d30da42e937db621564Steve Blockinline ThreadSpecific<T>::ThreadSpecific() 122d0825bca7fe65beaee391d30da42e937db621564Steve Block : m_value(0) 123d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 124d0825bca7fe65beaee391d30da42e937db621564Steve Block} 125d0825bca7fe65beaee391d30da42e937db621564Steve Block 126d0825bca7fe65beaee391d30da42e937db621564Steve Blocktemplate<typename T> 127d0825bca7fe65beaee391d30da42e937db621564Steve Blockinline T* ThreadSpecific<T>::get() 128d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 129d0825bca7fe65beaee391d30da42e937db621564Steve Block return m_value; 130d0825bca7fe65beaee391d30da42e937db621564Steve Block} 131d0825bca7fe65beaee391d30da42e937db621564Steve Block 132d0825bca7fe65beaee391d30da42e937db621564Steve Blocktemplate<typename T> 133d0825bca7fe65beaee391d30da42e937db621564Steve Blockinline void ThreadSpecific<T>::set(T* ptr) 134d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 135d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(!get()); 136d0825bca7fe65beaee391d30da42e937db621564Steve Block m_value = ptr; 137d0825bca7fe65beaee391d30da42e937db621564Steve Block} 138d0825bca7fe65beaee391d30da42e937db621564Steve Block#else 139635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#if USE(PTHREADS) 1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projecttemplate<typename T> 1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectinline ThreadSpecific<T>::ThreadSpecific() 1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int error = pthread_key_create(&m_key, destroy); 1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (error) 1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CRASH(); 1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projecttemplate<typename T> 1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectinline T* ThreadSpecific<T>::get() 1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Data* data = static_cast<Data*>(pthread_getspecific(m_key)); 1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return data ? data->value : 0; 1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projecttemplate<typename T> 1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectinline void ThreadSpecific<T>::set(T* ptr) 1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(!get()); 1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pthread_setspecific(m_key, new Data(ptr, this)); 1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1625f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#elif PLATFORM(QT) 1635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 1645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qiantemplate<typename T> 1655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianinline ThreadSpecific<T>::ThreadSpecific() 1665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 1675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} 1685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 1695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qiantemplate<typename T> 1705f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianinline T* ThreadSpecific<T>::get() 1715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 1725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian Data* data = static_cast<Data*>(m_key.localData()); 1735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return data ? data->value : 0; 1745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} 1755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 1765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qiantemplate<typename T> 1775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianinline void ThreadSpecific<T>::set(T* ptr) 1785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 1795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian ASSERT(!get()); 1805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian Data* data = new Data(ptr, this); 1815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian m_key.setLocalData(data); 1825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} 1835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 18406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#elif PLATFORM(GTK) 18506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen 18606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsentemplate<typename T> 18706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monseninline ThreadSpecific<T>::ThreadSpecific() 18806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen{ 18906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen g_static_private_init(&m_key); 19006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen} 19106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen 19206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsentemplate<typename T> 19306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monseninline T* ThreadSpecific<T>::get() 19406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen{ 19506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen Data* data = static_cast<Data*>(g_static_private_get(&m_key)); 19606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen return data ? data->value : 0; 19706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen} 19806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen 19906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsentemplate<typename T> 20006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monseninline void ThreadSpecific<T>::set(T* ptr) 20106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen{ 20206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen ASSERT(!get()); 20306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen Data* data = new Data(ptr, this); 20406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen g_static_private_set(&m_key, data, destroy); 20506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen} 20606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen 207d0825bca7fe65beaee391d30da42e937db621564Steve Block#elif OS(WINDOWS) 208d0825bca7fe65beaee391d30da42e937db621564Steve Block 209d0825bca7fe65beaee391d30da42e937db621564Steve Block// TLS_OUT_OF_INDEXES is not defined on WinCE. 210d0825bca7fe65beaee391d30da42e937db621564Steve Block#ifndef TLS_OUT_OF_INDEXES 211d0825bca7fe65beaee391d30da42e937db621564Steve Block#define TLS_OUT_OF_INDEXES 0xffffffff 212d0825bca7fe65beaee391d30da42e937db621564Steve Block#endif 213635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 214635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project// The maximum number of TLS keys that can be created. For simplification, we assume that: 215635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project// 1) Once the instance of ThreadSpecific<> is created, it will not be destructed until the program dies. 216635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project// 2) We do not need to hold many instances of ThreadSpecific<> data. This fixed number should be far enough. 217635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectconst int kMaxTlsKeySize = 256; 218635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianlong& tlsKeyCount(); 2208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianDWORD* tlsKeys(); 221635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 222635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projecttemplate<typename T> 223635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline ThreadSpecific<T>::ThreadSpecific() 224635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project : m_index(-1) 225635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 226d0825bca7fe65beaee391d30da42e937db621564Steve Block DWORD tlsKey = TlsAlloc(); 227d0825bca7fe65beaee391d30da42e937db621564Steve Block if (tlsKey == TLS_OUT_OF_INDEXES) 228635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CRASH(); 229635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian m_index = InterlockedIncrement(&tlsKeyCount()) - 1; 231635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (m_index >= kMaxTlsKeySize) 232635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CRASH(); 233d0825bca7fe65beaee391d30da42e937db621564Steve Block tlsKeys()[m_index] = tlsKey; 234635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 235635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 236635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projecttemplate<typename T> 237635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline ThreadSpecific<T>::~ThreadSpecific() 238635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 239635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Does not invoke destructor functions. They will be called from ThreadSpecificThreadExit when the thread is detached. 2408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian TlsFree(tlsKeys()[m_index]); 241635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 242635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 243635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projecttemplate<typename T> 244635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline T* ThreadSpecific<T>::get() 245635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 2468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian Data* data = static_cast<Data*>(TlsGetValue(tlsKeys()[m_index])); 247635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return data ? data->value : 0; 248635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 249635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 250635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projecttemplate<typename T> 251635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectinline void ThreadSpecific<T>::set(T* ptr) 252635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 253635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(!get()); 254635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project Data* data = new Data(ptr, this); 255635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project data->destructor = &ThreadSpecific<T>::destroy; 2568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian TlsSetValue(tlsKeys()[m_index], data); 257635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 258635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 259635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#else 260635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#error ThreadSpecific is not implemented for this platform. 261635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 262d0825bca7fe65beaee391d30da42e937db621564Steve Block#endif 263635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projecttemplate<typename T> 2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectinline void ThreadSpecific<T>::destroy(void* ptr) 2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 267d0825bca7fe65beaee391d30da42e937db621564Steve Block#if !ENABLE(SINGLE_THREADED) 2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Data* data = static_cast<Data*>(ptr); 2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 270635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#if USE(PTHREADS) 271635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // We want get() to keep working while data destructor works, because it can be called indirectly by the destructor. 272635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Some pthreads implementations zero out the pointer before calling destroy(), so we temporarily reset it. 273635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project pthread_setspecific(data->owner->m_key, ptr); 27406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#elif PLATFORM(GTK) 27506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen // See comment as above 27606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen g_static_private_set(&data->owner->m_key, data, 0); 277635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 278231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#if PLATFORM(QT) 279231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // See comment as above 280231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block data->owner->m_key.setLocalData(data); 281231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif 282231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 283635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project data->value->~T(); 284635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project fastFree(data->value); 285635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 286635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#if USE(PTHREADS) 287635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project pthread_setspecific(data->owner->m_key, 0); 2885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#elif PLATFORM(QT) 289231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // Do nothing here 29006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#elif PLATFORM(GTK) 29106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen g_static_private_set(&data->owner->m_key, 0, 0); 292d0825bca7fe65beaee391d30da42e937db621564Steve Block#elif OS(WINDOWS) 2938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian TlsSetValue(tlsKeys()[data->owner->m_index], 0); 2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else 2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#error ThreadSpecific is not implemented for this platform. 2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 298231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#if !PLATFORM(QT) 299635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project delete data; 300231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif 301d0825bca7fe65beaee391d30da42e937db621564Steve Block#endif 302635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 303635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projecttemplate<typename T> 3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectinline ThreadSpecific<T>::operator T*() 3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project T* ptr = static_cast<T*>(get()); 3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!ptr) { 309635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Set up thread-specific value's memory pointer before invoking constructor, in case any function it calls 310635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // needs to access the value, to avoid recursion. 31106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen ptr = static_cast<T*>(fastZeroedMalloc(sizeof(T))); 3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project set(ptr); 313635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project new (ptr) T; 3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return ptr; 3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projecttemplate<typename T> 3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectinline T* ThreadSpecific<T>::operator->() 3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return operator T*(); 3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projecttemplate<typename T> 3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectinline T& ThreadSpecific<T>::operator*() 3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return *operator T*(); 3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 333