2 * Copyright (C) 2009 Jian Li <jianli@chromium.org>
3 * Copyright (C) 2012 Patrick Gansterer <paroga@paroga.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
23 #include "ThreadSpecific.h"
27 #include "StdLibExtras.h"
28 #include "ThreadingPrimitives.h"
29 #include "wtf/DoublyLinkedList.h"
33 static DoublyLinkedList
<PlatformThreadSpecificKey
>& destructorsList()
35 DEFINE_STATIC_LOCAL(DoublyLinkedList
<PlatformThreadSpecificKey
>, staticList
, ());
39 static Mutex
& destructorsMutex()
41 DEFINE_STATIC_LOCAL(Mutex
, staticMutex
, ());
45 class PlatformThreadSpecificKey
: public DoublyLinkedListNode
<PlatformThreadSpecificKey
> {
47 friend class DoublyLinkedListNode
<PlatformThreadSpecificKey
>;
49 PlatformThreadSpecificKey(void (*destructor
)(void *))
50 : m_destructor(destructor
)
52 m_tlsKey
= TlsAlloc();
53 if (m_tlsKey
== TLS_OUT_OF_INDEXES
)
57 ~PlatformThreadSpecificKey()
62 void setValue(void* data
) { TlsSetValue(m_tlsKey
, data
); }
63 void* value() { return TlsGetValue(m_tlsKey
); }
67 if (void* data
= value())
72 void (*m_destructor
)(void *);
74 PlatformThreadSpecificKey
* m_prev
;
75 PlatformThreadSpecificKey
* m_next
;
86 static DWORD keys
[kMaxTlsKeySize
];
90 void threadSpecificKeyCreate(ThreadSpecificKey
* key
, void (*destructor
)(void *))
92 *key
= new PlatformThreadSpecificKey(destructor
);
94 MutexLocker
locker(destructorsMutex());
95 destructorsList().push(*key
);
98 void threadSpecificKeyDelete(ThreadSpecificKey key
)
100 MutexLocker
locker(destructorsMutex());
101 destructorsList().remove(key
);
105 void threadSpecificSet(ThreadSpecificKey key
, void* data
)
110 void* threadSpecificGet(ThreadSpecificKey key
)
115 void ThreadSpecificThreadExit()
117 for (long i
= 0; i
< tlsKeyCount(); i
++) {
118 // The layout of ThreadSpecific<T>::Data does not depend on T. So we are safe to do the static cast to ThreadSpecific<int> in order to access its data member.
119 ThreadSpecific
<int>::Data
* data
= static_cast<ThreadSpecific
<int>::Data
*>(TlsGetValue(tlsKeys()[i
]));
121 data
->destructor(data
);
124 MutexLocker
locker(destructorsMutex());
125 PlatformThreadSpecificKey
* key
= destructorsList().head();
127 PlatformThreadSpecificKey
* nextKey
= key
->next();
128 key
->callDestructor();