Home | History | Annotate | Download | only in core
      1 #include "SkTLS.h"
      2 
      3 // 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 
     12 struct SkTLSRec {
     13     SkTLSRec*           fNext;
     14     void*               fData;
     15     SkTLS::CreateProc   fCreateProc;
     16     SkTLS::DeleteProc   fDeleteProc;
     17 
     18 #ifdef SK_TRACE_TLS_LIFETIME
     19     SkTLSRec() {
     20         int n = sk_atomic_inc(&gTLSRecCount);
     21         SkDebugf(" SkTLSRec[%d]\n", n);
     22     }
     23 #endif
     24 
     25     ~SkTLSRec() {
     26         if (fDeleteProc) {
     27             fDeleteProc(fData);
     28         }
     29         // else we leak fData, or it will be managed by the caller
     30 
     31 #ifdef SK_TRACE_TLS_LIFETIME
     32         int n = sk_atomic_dec(&gTLSRecCount);
     33         SkDebugf("~SkTLSRec[%d]\n", n - 1);
     34 #endif
     35     }
     36 };
     37 
     38 void SkTLS::Destructor(void* ptr) {
     39 #ifdef SK_TRACE_TLS_LIFETIME
     40     SkDebugf("SkTLS::Destructor(%p)\n", ptr);
     41 #endif
     42 
     43     SkTLSRec* rec = (SkTLSRec*)ptr;
     44     do {
     45         SkTLSRec* next = rec->fNext;
     46         SkDELETE(rec);
     47         rec = next;
     48     } while (NULL != rec);
     49 }
     50 
     51 void* SkTLS::Get(CreateProc createProc, DeleteProc deleteProc) {
     52     if (NULL == createProc) {
     53         return NULL;
     54     }
     55 
     56     void* ptr = SkTLS::PlatformGetSpecific(true);
     57 
     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     }
     68 
     69     // 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 
     81 void* SkTLS::Find(CreateProc createProc) {
     82     if (NULL == createProc) {
     83         return NULL;
     84     }
     85 
     86     void* ptr = SkTLS::PlatformGetSpecific(false);
     87 
     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 
     99 void SkTLS::Delete(CreateProc createProc) {
    100     if (NULL == createProc) {
    101         return;
    102     }
    103 
    104     void* ptr = SkTLS::PlatformGetSpecific(false);
    105 
    106     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 }
    124