Home | History | Annotate | Download | only in core
      1 /*
      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 
      8 #include "SkTLS.h"
      9 
     10 // enable to help debug TLS storage
     11 //#define SK_TRACE_TLS_LIFETIME
     12 
     13 
     14 #ifdef SK_TRACE_TLS_LIFETIME
     15     #include "SkAtomics.h"
     16     static int32_t gTLSRecCount;
     17 #endif
     18 
     19 struct SkTLSRec {
     20     SkTLSRec*           fNext;
     21     void*               fData;
     22     SkTLS::CreateProc   fCreateProc;
     23     SkTLS::DeleteProc   fDeleteProc;
     24 
     25 #ifdef SK_TRACE_TLS_LIFETIME
     26     SkTLSRec() {
     27         int n = sk_atomic_inc(&gTLSRecCount);
     28         SkDebugf(" SkTLSRec[%d]\n", n);
     29     }
     30 #endif
     31 
     32     ~SkTLSRec() {
     33         if (fDeleteProc) {
     34             fDeleteProc(fData);
     35         }
     36         // else we leak fData, or it will be managed by the caller
     37 
     38 #ifdef SK_TRACE_TLS_LIFETIME
     39         int n = sk_atomic_dec(&gTLSRecCount);
     40         SkDebugf("~SkTLSRec[%d]\n", n - 1);
     41 #endif
     42     }
     43 };
     44 
     45 void SkTLS::Destructor(void* ptr) {
     46 #ifdef SK_TRACE_TLS_LIFETIME
     47     SkDebugf("SkTLS::Destructor(%p)\n", ptr);
     48 #endif
     49 
     50     SkTLSRec* rec = (SkTLSRec*)ptr;
     51     do {
     52         SkTLSRec* next = rec->fNext;
     53         delete rec;
     54         rec = next;
     55     } while (rec);
     56 }
     57 
     58 void* SkTLS::Get(CreateProc createProc, DeleteProc deleteProc) {
     59     if (nullptr == createProc) {
     60         return nullptr;
     61     }
     62 
     63     void* ptr = SkTLS::PlatformGetSpecific(true);
     64 
     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             }
     72         } while ((rec = rec->fNext) != nullptr);
     73         // not found, so create a new one
     74     }
     75 
     76     // 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 
     88 void* SkTLS::Find(CreateProc createProc) {
     89     if (nullptr == createProc) {
     90         return nullptr;
     91     }
     92 
     93     void* ptr = SkTLS::PlatformGetSpecific(false);
     94 
     95     if (ptr) {
     96         const SkTLSRec* rec = (const SkTLSRec*)ptr;
     97         do {
     98             if (rec->fCreateProc == createProc) {
     99                 return rec->fData;
    100             }
    101         } while ((rec = rec->fNext) != nullptr);
    102     }
    103     return nullptr;
    104 }
    105 
    106 void SkTLS::Delete(CreateProc createProc) {
    107     if (nullptr == createProc) {
    108         return;
    109     }
    110 
    111     void* ptr = SkTLS::PlatformGetSpecific(false);
    112 
    113     SkTLSRec* curr = (SkTLSRec*)ptr;
    114     SkTLSRec* prev = nullptr;
    115     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             }
    124             delete curr;
    125             break;
    126         }
    127         prev = curr;
    128         curr = next;
    129     }
    130 }
    131