cb1b32d3258a85803e01f9b4906a49a30960e5d6
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / common / tls.cpp
1 //
2 // Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // tls.cpp: Simple cross-platform interface for thread local storage.
8
9 #include "common/tls.h"
10
11 #include <assert.h>
12
13 #ifdef ANGLE_ENABLE_WINDOWS_STORE
14 #include <vector>
15 #include <set>
16 #include <map>
17 #include <mutex>
18
19 #include <wrl/client.h>
20 #include <wrl/async.h>
21 #include <Windows.System.Threading.h>
22
23 using namespace std;
24 using namespace Windows::Foundation;
25 using namespace ABI::Windows::System::Threading;
26
27 // Thread local storage for Windows Store support
28 typedef vector<void*> ThreadLocalData;
29
30 static __declspec(thread) ThreadLocalData* currentThreadData = nullptr;
31 static set<ThreadLocalData*> allThreadData;
32 static DWORD nextTlsIndex = 0;
33 static vector<DWORD> freeTlsIndices;
34
35 #endif
36
37 TLSIndex CreateTLSIndex()
38 {
39     TLSIndex index;
40
41 #ifdef ANGLE_PLATFORM_WINDOWS
42 #ifdef ANGLE_ENABLE_WINDOWS_STORE
43     if (!freeTlsIndices.empty())
44     {
45         DWORD result = freeTlsIndices.back();
46         freeTlsIndices.pop_back();
47         index = result;
48     }
49     else
50     {
51         index = nextTlsIndex++;
52     }
53 #else
54     index = TlsAlloc();
55 #endif
56
57 #elif defined(ANGLE_PLATFORM_POSIX)
58     // Create global pool key
59     if ((pthread_key_create(&index, NULL)) != 0)
60     {
61         index = TLS_INVALID_INDEX;
62     }
63 #endif
64
65     assert(index != TLS_INVALID_INDEX && "CreateTLSIndex(): Unable to allocate Thread Local Storage");
66     return index;
67 }
68
69 bool DestroyTLSIndex(TLSIndex index)
70 {
71     assert(index != TLS_INVALID_INDEX && "DestroyTLSIndex(): Invalid TLS Index");
72     if (index == TLS_INVALID_INDEX)
73     {
74         return false;
75     }
76
77 #ifdef ANGLE_PLATFORM_WINDOWS
78 #ifdef ANGLE_ENABLE_WINDOWS_STORE
79     assert(index < nextTlsIndex);
80     assert(find(freeTlsIndices.begin(), freeTlsIndices.end(), index) == freeTlsIndices.end());
81
82     freeTlsIndices.push_back(index);
83     for (auto threadData : allThreadData)
84     {
85         if (threadData->size() > index)
86         {
87             threadData->at(index) = nullptr;
88         }
89     }
90     return true;
91 #else
92     return (TlsFree(index) == TRUE);
93 #endif
94 #elif defined(ANGLE_PLATFORM_POSIX)
95     return (pthread_key_delete(index) == 0);
96 #endif
97 }
98
99 bool SetTLSValue(TLSIndex index, void *value)
100 {
101     assert(index != TLS_INVALID_INDEX && "SetTLSValue(): Invalid TLS Index");
102     if (index == TLS_INVALID_INDEX)
103     {
104         return false;
105     }
106
107 #ifdef ANGLE_PLATFORM_WINDOWS
108 #ifdef ANGLE_ENABLE_WINDOWS_STORE
109     ThreadLocalData* threadData = currentThreadData;
110     if (!threadData)
111     {
112         threadData = new ThreadLocalData(index + 1, nullptr);
113         allThreadData.insert(threadData);
114         currentThreadData = threadData;
115     }
116     else if (threadData->size() <= index)
117     {
118         threadData->resize(index + 1, nullptr);
119     }
120
121     threadData->at(index) = value;
122     return true;
123 #else
124     return (TlsSetValue(index, value) == TRUE);
125 #endif
126 #elif defined(ANGLE_PLATFORM_POSIX)
127     return (pthread_setspecific(index, value) == 0);
128 #endif
129 }
130
131 void *GetTLSValue(TLSIndex index)
132 {
133     assert(index != TLS_INVALID_INDEX && "GetTLSValue(): Invalid TLS Index");
134     if (index == TLS_INVALID_INDEX)
135     {
136         return NULL;
137     }
138
139 #ifdef ANGLE_PLATFORM_WINDOWS
140 #ifdef ANGLE_ENABLE_WINDOWS_STORE
141     ThreadLocalData* threadData = currentThreadData;
142     if (threadData && threadData->size() > index)
143     {
144         return threadData->at(index);
145     }
146     else
147     {
148         return nullptr;
149     }
150 #else
151     return TlsGetValue(index);
152 #endif
153 #elif defined(ANGLE_PLATFORM_POSIX)
154     return pthread_getspecific(index);
155 #endif
156 }