blob: 3f78a2434cfdf452597495a4ec0ad5463f4f096e [file] [log] [blame]
reed@google.com48ca7e32012-05-07 20:23:27 +00001#include "SkTLS.h"
2
reed@google.com7b578922012-05-21 15:29:27 +00003// enable to help debug TLS storage
4//#define SK_TRACE_TLS_LIFETIME
5
6
7#ifdef SK_TRACE_TLS_LIFETIME
8 #include "SkThread.h"
9 static int32_t gTLSRecCount;
10#endif
11
reed@google.com48ca7e32012-05-07 20:23:27 +000012struct SkTLSRec {
13 SkTLSRec* fNext;
14 void* fData;
15 SkTLS::CreateProc fCreateProc;
16 SkTLS::DeleteProc fDeleteProc;
17
reed@google.com7b578922012-05-21 15:29:27 +000018#ifdef SK_TRACE_TLS_LIFETIME
19 SkTLSRec() {
20 int n = sk_atomic_inc(&gTLSRecCount);
21 SkDebugf(" SkTLSRec[%d]\n", n);
22 }
23#endif
24
reed@google.com48ca7e32012-05-07 20:23:27 +000025 ~SkTLSRec() {
26 if (fDeleteProc) {
27 fDeleteProc(fData);
28 }
29 // else we leak fData, or it will be managed by the caller
reed@google.com7b578922012-05-21 15:29:27 +000030
31#ifdef SK_TRACE_TLS_LIFETIME
32 int n = sk_atomic_dec(&gTLSRecCount);
33 SkDebugf("~SkTLSRec[%d]\n", n - 1);
34#endif
reed@google.com48ca7e32012-05-07 20:23:27 +000035 }
36};
37
38void SkTLS::Destructor(void* ptr) {
reed@google.com7b578922012-05-21 15:29:27 +000039#ifdef SK_TRACE_TLS_LIFETIME
40 SkDebugf("SkTLS::Destructor(%p)\n", ptr);
41#endif
42
reed@google.com48ca7e32012-05-07 20:23:27 +000043 SkTLSRec* rec = (SkTLSRec*)ptr;
44 do {
45 SkTLSRec* next = rec->fNext;
46 SkDELETE(rec);
47 rec = next;
bsalomon49f085d2014-09-05 13:34:00 -070048 } while (rec);
reed@google.com48ca7e32012-05-07 20:23:27 +000049}
50
51void* SkTLS::Get(CreateProc createProc, DeleteProc deleteProc) {
52 if (NULL == createProc) {
53 return NULL;
54 }
55
reed@google.com331e2dc2012-05-08 21:45:03 +000056 void* ptr = SkTLS::PlatformGetSpecific(true);
reed@google.com48ca7e32012-05-07 20:23:27 +000057
58 if (ptr) {
59 const SkTLSRec* rec = (const SkTLSRec*)ptr;
60 do {
61 if (rec->fCreateProc == createProc) {
62 SkASSERT(rec->fDeleteProc == deleteProc);
63 return rec->fData;
64 }
65 } while ((rec = rec->fNext) != NULL);
66 // not found, so create a new one
67 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +000068
reed@google.com48ca7e32012-05-07 20:23:27 +000069 // add a new head of our change
70 SkTLSRec* rec = new SkTLSRec;
71 rec->fNext = (SkTLSRec*)ptr;
72
73 SkTLS::PlatformSetSpecific(rec);
74
75 rec->fData = createProc();
76 rec->fCreateProc = createProc;
77 rec->fDeleteProc = deleteProc;
78 return rec->fData;
79}
80
81void* SkTLS::Find(CreateProc createProc) {
82 if (NULL == createProc) {
83 return NULL;
84 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +000085
reed@google.com331e2dc2012-05-08 21:45:03 +000086 void* ptr = SkTLS::PlatformGetSpecific(false);
reed@google.com48ca7e32012-05-07 20:23:27 +000087
88 if (ptr) {
89 const SkTLSRec* rec = (const SkTLSRec*)ptr;
90 do {
91 if (rec->fCreateProc == createProc) {
92 return rec->fData;
93 }
94 } while ((rec = rec->fNext) != NULL);
95 }
96 return NULL;
97}
98
99void SkTLS::Delete(CreateProc createProc) {
100 if (NULL == createProc) {
101 return;
102 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000103
reed@google.com331e2dc2012-05-08 21:45:03 +0000104 void* ptr = SkTLS::PlatformGetSpecific(false);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000105
reed@google.com48ca7e32012-05-07 20:23:27 +0000106 SkTLSRec* curr = (SkTLSRec*)ptr;
107 SkTLSRec* prev = NULL;
108 while (curr) {
109 SkTLSRec* next = curr->fNext;
110 if (curr->fCreateProc == createProc) {
111 if (prev) {
112 prev->fNext = next;
113 } else {
114 // we have a new head of our chain
115 SkTLS::PlatformSetSpecific(next);
116 }
117 SkDELETE(curr);
118 break;
119 }
120 prev = curr;
121 curr = next;
122 }
123}