blob: a47dc14b5af6a742e7400f34637751801439e766 [file] [log] [blame]
mtklein1b249332015-07-07 12:21:21 -07001/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
reed@google.com48ca7e32012-05-07 20:23:27 +00008#include "SkTLS.h"
9
reed@google.com7b578922012-05-21 15:29:27 +000010// enable to help debug TLS storage
11//#define SK_TRACE_TLS_LIFETIME
12
13
14#ifdef SK_TRACE_TLS_LIFETIME
herbb906daf2015-09-29 09:37:59 -070015 #include "SkAtomics.h"
reed@google.com7b578922012-05-21 15:29:27 +000016 static int32_t gTLSRecCount;
17#endif
18
reed@google.com48ca7e32012-05-07 20:23:27 +000019struct SkTLSRec {
20 SkTLSRec* fNext;
21 void* fData;
22 SkTLS::CreateProc fCreateProc;
23 SkTLS::DeleteProc fDeleteProc;
24
reed@google.com7b578922012-05-21 15:29:27 +000025#ifdef SK_TRACE_TLS_LIFETIME
26 SkTLSRec() {
27 int n = sk_atomic_inc(&gTLSRecCount);
28 SkDebugf(" SkTLSRec[%d]\n", n);
29 }
30#endif
31
reed@google.com48ca7e32012-05-07 20:23:27 +000032 ~SkTLSRec() {
33 if (fDeleteProc) {
34 fDeleteProc(fData);
35 }
36 // else we leak fData, or it will be managed by the caller
reed@google.com7b578922012-05-21 15:29:27 +000037
38#ifdef SK_TRACE_TLS_LIFETIME
39 int n = sk_atomic_dec(&gTLSRecCount);
40 SkDebugf("~SkTLSRec[%d]\n", n - 1);
41#endif
reed@google.com48ca7e32012-05-07 20:23:27 +000042 }
43};
44
45void SkTLS::Destructor(void* ptr) {
reed@google.com7b578922012-05-21 15:29:27 +000046#ifdef SK_TRACE_TLS_LIFETIME
47 SkDebugf("SkTLS::Destructor(%p)\n", ptr);
48#endif
49
reed@google.com48ca7e32012-05-07 20:23:27 +000050 SkTLSRec* rec = (SkTLSRec*)ptr;
51 do {
52 SkTLSRec* next = rec->fNext;
halcanary385fe4d2015-08-26 13:07:48 -070053 delete rec;
reed@google.com48ca7e32012-05-07 20:23:27 +000054 rec = next;
bsalomon49f085d2014-09-05 13:34:00 -070055 } while (rec);
reed@google.com48ca7e32012-05-07 20:23:27 +000056}
57
58void* SkTLS::Get(CreateProc createProc, DeleteProc deleteProc) {
halcanary96fcdcc2015-08-27 07:41:13 -070059 if (nullptr == createProc) {
60 return nullptr;
reed@google.com48ca7e32012-05-07 20:23:27 +000061 }
62
reed@google.com331e2dc2012-05-08 21:45:03 +000063 void* ptr = SkTLS::PlatformGetSpecific(true);
reed@google.com48ca7e32012-05-07 20:23:27 +000064
65 if (ptr) {
66 const SkTLSRec* rec = (const SkTLSRec*)ptr;
67 do {
68 if (rec->fCreateProc == createProc) {
69 SkASSERT(rec->fDeleteProc == deleteProc);
70 return rec->fData;
71 }
halcanary96fcdcc2015-08-27 07:41:13 -070072 } while ((rec = rec->fNext) != nullptr);
reed@google.com48ca7e32012-05-07 20:23:27 +000073 // not found, so create a new one
74 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +000075
reed@google.com48ca7e32012-05-07 20:23:27 +000076 // add a new head of our change
77 SkTLSRec* rec = new SkTLSRec;
78 rec->fNext = (SkTLSRec*)ptr;
79
80 SkTLS::PlatformSetSpecific(rec);
81
82 rec->fData = createProc();
83 rec->fCreateProc = createProc;
84 rec->fDeleteProc = deleteProc;
85 return rec->fData;
86}
87
88void* SkTLS::Find(CreateProc createProc) {
halcanary96fcdcc2015-08-27 07:41:13 -070089 if (nullptr == createProc) {
90 return nullptr;
reed@google.com48ca7e32012-05-07 20:23:27 +000091 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +000092
reed@google.com331e2dc2012-05-08 21:45:03 +000093 void* ptr = SkTLS::PlatformGetSpecific(false);
reed@google.com48ca7e32012-05-07 20:23:27 +000094
95 if (ptr) {
96 const SkTLSRec* rec = (const SkTLSRec*)ptr;
97 do {
98 if (rec->fCreateProc == createProc) {
99 return rec->fData;
100 }
halcanary96fcdcc2015-08-27 07:41:13 -0700101 } while ((rec = rec->fNext) != nullptr);
reed@google.com48ca7e32012-05-07 20:23:27 +0000102 }
halcanary96fcdcc2015-08-27 07:41:13 -0700103 return nullptr;
reed@google.com48ca7e32012-05-07 20:23:27 +0000104}
105
106void SkTLS::Delete(CreateProc createProc) {
halcanary96fcdcc2015-08-27 07:41:13 -0700107 if (nullptr == createProc) {
reed@google.com48ca7e32012-05-07 20:23:27 +0000108 return;
109 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000110
reed@google.com331e2dc2012-05-08 21:45:03 +0000111 void* ptr = SkTLS::PlatformGetSpecific(false);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000112
reed@google.com48ca7e32012-05-07 20:23:27 +0000113 SkTLSRec* curr = (SkTLSRec*)ptr;
halcanary96fcdcc2015-08-27 07:41:13 -0700114 SkTLSRec* prev = nullptr;
reed@google.com48ca7e32012-05-07 20:23:27 +0000115 while (curr) {
116 SkTLSRec* next = curr->fNext;
117 if (curr->fCreateProc == createProc) {
118 if (prev) {
119 prev->fNext = next;
120 } else {
121 // we have a new head of our chain
122 SkTLS::PlatformSetSpecific(next);
123 }
halcanary385fe4d2015-08-26 13:07:48 -0700124 delete curr;
reed@google.com48ca7e32012-05-07 20:23:27 +0000125 break;
126 }
127 prev = curr;
128 curr = next;
129 }
130}