blob: da2e0d4a2cde126e880edd1718ae293f6ad7a855 [file] [log] [blame]
[email protected]dd99f5392009-01-08 16:47:141/*
2 * Copyright (C) 2009 Jian Li <[email protected]>
[email protected]58d30e42012-08-07 00:29:143 * Copyright (C) 2012 Patrick Gansterer <[email protected]>
[email protected]dd99f5392009-01-08 16:47:144 *
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.
9 *
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.
14 *
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.
19 *
20 */
21
[email protected]dd99f5392009-01-08 16:47:1422#include "ThreadSpecific.h"
[email protected]dd99f5392009-01-08 16:47:1423
[email protected]ac08cdb2013-09-08 22:51:5324#if OS(WIN)
[email protected]7b983e82013-01-17 10:04:4525
[email protected]58d30e42012-08-07 00:29:1426#include "StdLibExtras.h"
27#include "ThreadingPrimitives.h"
tasak4faca4c42016-01-19 08:38:5528#include "wtf/Allocator.h"
[email protected]a71b3132013-06-27 17:54:1529#include "wtf/DoublyLinkedList.h"
[email protected]58d30e42012-08-07 00:29:1430
[email protected]dd99f5392009-01-08 16:47:1431namespace WTF {
32
[email protected]58d30e42012-08-07 00:29:1433static DoublyLinkedList<PlatformThreadSpecificKey>& destructorsList()
34{
35 DEFINE_STATIC_LOCAL(DoublyLinkedList<PlatformThreadSpecificKey>, staticList, ());
36 return staticList;
37}
38
39static Mutex& destructorsMutex()
40{
41 DEFINE_STATIC_LOCAL(Mutex, staticMutex, ());
42 return staticMutex;
43}
44
45class PlatformThreadSpecificKey : public DoublyLinkedListNode<PlatformThreadSpecificKey> {
tasak4faca4c42016-01-19 08:38:5546 USING_FAST_MALLOC(PlatformThreadSpecificKey);
47 WTF_MAKE_NONCOPYABLE(PlatformThreadSpecificKey);
[email protected]58d30e42012-08-07 00:29:1448public:
49 friend class DoublyLinkedListNode<PlatformThreadSpecificKey>;
50
51 PlatformThreadSpecificKey(void (*destructor)(void *))
52 : m_destructor(destructor)
53 {
54 m_tlsKey = TlsAlloc();
55 if (m_tlsKey == TLS_OUT_OF_INDEXES)
56 CRASH();
57 }
58
59 ~PlatformThreadSpecificKey()
60 {
61 TlsFree(m_tlsKey);
62 }
63
64 void setValue(void* data) { TlsSetValue(m_tlsKey, data); }
65 void* value() { return TlsGetValue(m_tlsKey); }
66
67 void callDestructor()
68 {
tkentbee51202015-09-30 07:59:2569 if (void* data = value())
[email protected]58d30e42012-08-07 00:29:1470 m_destructor(data);
71 }
72
73private:
74 void (*m_destructor)(void *);
75 DWORD m_tlsKey;
76 PlatformThreadSpecificKey* m_prev;
77 PlatformThreadSpecificKey* m_next;
78};
79
[email protected]8ad682d2009-03-11 20:39:2180long& tlsKeyCount()
81{
82 static long count;
83 return count;
84}
85
86DWORD* tlsKeys()
87{
88 static DWORD keys[kMaxTlsKeySize];
89 return keys;
90}
[email protected]dd99f5392009-01-08 16:47:1491
[email protected]58d30e42012-08-07 00:29:1492void threadSpecificKeyCreate(ThreadSpecificKey* key, void (*destructor)(void *))
93{
94 *key = new PlatformThreadSpecificKey(destructor);
95
96 MutexLocker locker(destructorsMutex());
97 destructorsList().push(*key);
98}
99
100void threadSpecificKeyDelete(ThreadSpecificKey key)
101{
102 MutexLocker locker(destructorsMutex());
103 destructorsList().remove(key);
104 delete key;
105}
106
107void threadSpecificSet(ThreadSpecificKey key, void* data)
108{
109 key->setValue(data);
110}
111
112void* threadSpecificGet(ThreadSpecificKey key)
113{
114 return key->value();
115}
116
[email protected]dd99f5392009-01-08 16:47:14117void ThreadSpecificThreadExit()
118{
[email protected]8ad682d2009-03-11 20:39:21119 for (long i = 0; i < tlsKeyCount(); i++) {
[email protected]dd99f5392009-01-08 16:47:14120 // 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.
[email protected]8ad682d2009-03-11 20:39:21121 ThreadSpecific<int>::Data* data = static_cast<ThreadSpecific<int>::Data*>(TlsGetValue(tlsKeys()[i]));
[email protected]dd99f5392009-01-08 16:47:14122 if (data)
123 data->destructor(data);
124 }
[email protected]58d30e42012-08-07 00:29:14125
126 MutexLocker locker(destructorsMutex());
127 PlatformThreadSpecificKey* key = destructorsList().head();
128 while (key) {
129 PlatformThreadSpecificKey* nextKey = key->next();
130 key->callDestructor();
131 key = nextKey;
132 }
[email protected]dd99f5392009-01-08 16:47:14133}
134
135} // namespace WTF
[email protected]58d30e42012-08-07 00:29:14136
[email protected]ac08cdb2013-09-08 22:51:53137#endif // OS(WIN)