Unreviewed, roll out http://trac.webkit.org/changeset/187972.
[WebKit-https.git] / Source / WTF / wtf / ThreadSpecificWin.cpp
1 /*
2  * Copyright (C) 2009 Jian Li <jianli@chromium.org>
3  * Copyright (C) 2012 Patrick Gansterer <paroga@paroga.com>
4  *
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
22 #include "config.h"
23 #include "ThreadSpecific.h"
24
25 #if OS(WINDOWS)
26
27 #include "StdLibExtras.h"
28 #include "ThreadingPrimitives.h"
29 #include <wtf/DoublyLinkedList.h>
30
31 #if !USE(PTHREADS)
32
33 namespace WTF {
34
35 static DoublyLinkedList<PlatformThreadSpecificKey>& destructorsList()
36 {
37     static DoublyLinkedList<PlatformThreadSpecificKey> staticList;
38     return staticList;
39 }
40
41 static Mutex& destructorsMutex()
42 {
43     static Mutex staticMutex;
44     return staticMutex;
45 }
46
47 class PlatformThreadSpecificKey : public DoublyLinkedListNode<PlatformThreadSpecificKey> {
48 public:
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     {
69        if (void* data = value())
70             m_destructor(data);
71     }
72
73 private:
74     void (*m_destructor)(void *);
75     DWORD m_tlsKey;
76     PlatformThreadSpecificKey* m_prev;
77     PlatformThreadSpecificKey* m_next;
78 };
79
80 long& tlsKeyCount()
81 {
82     static long count;
83     return count;
84 }
85
86 DWORD* tlsKeys()
87 {
88     static DWORD keys[kMaxTlsKeySize];
89     return keys;
90 }
91
92 void threadSpecificKeyCreate(ThreadSpecificKey* key, void (*destructor)(void *))
93 {
94     // Use the original malloc() instead of fastMalloc() to use this function in FastMalloc code.
95     *key = static_cast<PlatformThreadSpecificKey*>(::malloc(sizeof(PlatformThreadSpecificKey)));
96     new (*key) PlatformThreadSpecificKey(destructor);
97
98     MutexLocker locker(destructorsMutex());
99     destructorsList().push(*key);
100 }
101
102 void threadSpecificKeyDelete(ThreadSpecificKey key)
103 {
104     MutexLocker locker(destructorsMutex());
105     destructorsList().remove(key);
106     key->~PlatformThreadSpecificKey();
107     ::free(key);
108 }
109
110 void threadSpecificSet(ThreadSpecificKey key, void* data)
111 {
112     key->setValue(data);
113 }
114
115 void* threadSpecificGet(ThreadSpecificKey key)
116 {
117     return key->value();
118 }
119
120 void ThreadSpecificThreadExit()
121 {
122     for (long i = 0; i < tlsKeyCount(); i++) {
123         // 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.
124         ThreadSpecific<int>::Data* data = static_cast<ThreadSpecific<int>::Data*>(TlsGetValue(tlsKeys()[i]));
125         if (data)
126             data->destructor(data);
127     }
128
129     MutexLocker locker(destructorsMutex());
130     PlatformThreadSpecificKey* key = destructorsList().head();
131     while (key) {
132         PlatformThreadSpecificKey* nextKey = key->next();
133         key->callDestructor();
134         key = nextKey;
135     }
136 }
137
138 } // namespace WTF
139
140 #endif // !USE(PTHREADS)
141
142 #endif // OS(WINDOWS)