Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / wtf / ThreadSpecificWin.cpp
blob7426e0f49d846dfa9ffec31bf744637768a23232
1 /*
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.
22 #include "config.h"
23 #include "ThreadSpecific.h"
25 #if OS(WIN)
27 #include "StdLibExtras.h"
28 #include "ThreadingPrimitives.h"
29 #include "wtf/DoublyLinkedList.h"
31 namespace WTF {
33 static DoublyLinkedList<PlatformThreadSpecificKey>& destructorsList()
35 DEFINE_STATIC_LOCAL(DoublyLinkedList<PlatformThreadSpecificKey>, staticList, ());
36 return staticList;
39 static Mutex& destructorsMutex()
41 DEFINE_STATIC_LOCAL(Mutex, staticMutex, ());
42 return staticMutex;
45 class PlatformThreadSpecificKey : public DoublyLinkedListNode<PlatformThreadSpecificKey> {
46 public:
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)
54 CRASH();
57 ~PlatformThreadSpecificKey()
59 TlsFree(m_tlsKey);
62 void setValue(void* data) { TlsSetValue(m_tlsKey, data); }
63 void* value() { return TlsGetValue(m_tlsKey); }
65 void callDestructor()
67 if (void* data = value())
68 m_destructor(data);
71 private:
72 void (*m_destructor)(void *);
73 DWORD m_tlsKey;
74 PlatformThreadSpecificKey* m_prev;
75 PlatformThreadSpecificKey* m_next;
78 long& tlsKeyCount()
80 static long count;
81 return count;
84 DWORD* tlsKeys()
86 static DWORD keys[kMaxTlsKeySize];
87 return keys;
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);
102 delete key;
105 void threadSpecificSet(ThreadSpecificKey key, void* data)
107 key->setValue(data);
110 void* threadSpecificGet(ThreadSpecificKey key)
112 return key->value();
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]));
120 if (data)
121 data->destructor(data);
124 MutexLocker locker(destructorsMutex());
125 PlatformThreadSpecificKey* key = destructorsList().head();
126 while (key) {
127 PlatformThreadSpecificKey* nextKey = key->next();
128 key->callDestructor();
129 key = nextKey;
133 } // namespace WTF
135 #endif // OS(WIN)