• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(WIN)
26 
27 #include "StdLibExtras.h"
28 #include "ThreadingPrimitives.h"
29 #include "wtf/DoublyLinkedList.h"
30 
31 namespace WTF {
32 
destructorsList()33 static DoublyLinkedList<PlatformThreadSpecificKey>& destructorsList()
34 {
35     DEFINE_STATIC_LOCAL(DoublyLinkedList<PlatformThreadSpecificKey>, staticList, ());
36     return staticList;
37 }
38 
destructorsMutex()39 static Mutex& destructorsMutex()
40 {
41     DEFINE_STATIC_LOCAL(Mutex, staticMutex, ());
42     return staticMutex;
43 }
44 
45 class PlatformThreadSpecificKey : public DoublyLinkedListNode<PlatformThreadSpecificKey> {
46 public:
47     friend class DoublyLinkedListNode<PlatformThreadSpecificKey>;
48 
PlatformThreadSpecificKey(void (* destructor)(void *))49     PlatformThreadSpecificKey(void (*destructor)(void *))
50         : m_destructor(destructor)
51     {
52         m_tlsKey = TlsAlloc();
53         if (m_tlsKey == TLS_OUT_OF_INDEXES)
54             CRASH();
55     }
56 
~PlatformThreadSpecificKey()57     ~PlatformThreadSpecificKey()
58     {
59         TlsFree(m_tlsKey);
60     }
61 
setValue(void * data)62     void setValue(void* data) { TlsSetValue(m_tlsKey, data); }
value()63     void* value() { return TlsGetValue(m_tlsKey); }
64 
callDestructor()65     void callDestructor()
66     {
67        if (void* data = value())
68             m_destructor(data);
69     }
70 
71 private:
72     void (*m_destructor)(void *);
73     DWORD m_tlsKey;
74     PlatformThreadSpecificKey* m_prev;
75     PlatformThreadSpecificKey* m_next;
76 };
77 
tlsKeyCount()78 long& tlsKeyCount()
79 {
80     static long count;
81     return count;
82 }
83 
tlsKeys()84 DWORD* tlsKeys()
85 {
86     static DWORD keys[kMaxTlsKeySize];
87     return keys;
88 }
89 
threadSpecificKeyCreate(ThreadSpecificKey * key,void (* destructor)(void *))90 void threadSpecificKeyCreate(ThreadSpecificKey* key, void (*destructor)(void *))
91 {
92     *key = new PlatformThreadSpecificKey(destructor);
93 
94     MutexLocker locker(destructorsMutex());
95     destructorsList().push(*key);
96 }
97 
threadSpecificKeyDelete(ThreadSpecificKey key)98 void threadSpecificKeyDelete(ThreadSpecificKey key)
99 {
100     MutexLocker locker(destructorsMutex());
101     destructorsList().remove(key);
102     delete key;
103 }
104 
threadSpecificSet(ThreadSpecificKey key,void * data)105 void threadSpecificSet(ThreadSpecificKey key, void* data)
106 {
107     key->setValue(data);
108 }
109 
threadSpecificGet(ThreadSpecificKey key)110 void* threadSpecificGet(ThreadSpecificKey key)
111 {
112     return key->value();
113 }
114 
ThreadSpecificThreadExit()115 void ThreadSpecificThreadExit()
116 {
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]));
120         if (data)
121             data->destructor(data);
122     }
123 
124     MutexLocker locker(destructorsMutex());
125     PlatformThreadSpecificKey* key = destructorsList().head();
126     while (key) {
127         PlatformThreadSpecificKey* nextKey = key->next();
128         key->callDestructor();
129         key = nextKey;
130     }
131 }
132 
133 } // namespace WTF
134 
135 #endif // OS(WIN)
136