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 struct SkTLSRec {
     11     SkTLSRec*           fNext;
     12     void*               fData;
     13     SkTLS::CreateProc   fCreateProc;
     14     SkTLS::DeleteProc   fDeleteProc;
     15 
     16     ~SkTLSRec() {
     17         if (fDeleteProc) {
     18             fDeleteProc(fData);
     19         }
     20         // else we leak fData, or it will be managed by the caller
     21     }
     22 };
     23 
     24 void SkTLS::Destructor(void* ptr) {
     25     SkTLSRec* rec = (SkTLSRec*)ptr;
     26     do {
     27         SkTLSRec* next = rec->fNext;
     28         delete rec;
     29         rec = next;
     30     } while (rec);
     31 }
     32 
     33 void* SkTLS::Get(CreateProc createProc, DeleteProc deleteProc) {
     34     if (nullptr == createProc) {
     35         return nullptr;
     36     }
     37 
     38     void* ptr = SkTLS::PlatformGetSpecific(true);
     39 
     40     if (ptr) {
     41         const SkTLSRec* rec = (const SkTLSRec*)ptr;
     42         do {
     43             if (rec->fCreateProc == createProc) {
     44                 SkASSERT(rec->fDeleteProc == deleteProc);
     45                 return rec->fData;
     46             }
     47         } while ((rec = rec->fNext) != nullptr);
     48         // not found, so create a new one
     49     }
     50 
     51     // add a new head of our change
     52     SkTLSRec* rec = new SkTLSRec;
     53     rec->fNext = (SkTLSRec*)ptr;
     54 
     55     SkTLS::PlatformSetSpecific(rec);
     56 
     57     rec->fData = createProc();
     58     rec->fCreateProc = createProc;
     59     rec->fDeleteProc = deleteProc;
     60     return rec->fData;
     61 }
     62 
     63 void* SkTLS::Find(CreateProc createProc) {
     64     if (nullptr == createProc) {
     65         return nullptr;
     66     }
     67 
     68     void* ptr = SkTLS::PlatformGetSpecific(false);
     69 
     70     if (ptr) {
     71         const SkTLSRec* rec = (const SkTLSRec*)ptr;
     72         do {
     73             if (rec->fCreateProc == createProc) {
     74                 return rec->fData;
     75             }
     76         } while ((rec = rec->fNext) != nullptr);
     77     }
     78     return nullptr;
     79 }
     80 
     81 void SkTLS::Delete(CreateProc createProc) {
     82     if (nullptr == createProc) {
     83         return;
     84     }
     85 
     86     void* ptr = SkTLS::PlatformGetSpecific(false);
     87 
     88     SkTLSRec* curr = (SkTLSRec*)ptr;
     89     SkTLSRec* prev = nullptr;
     90     while (curr) {
     91         SkTLSRec* next = curr->fNext;
     92         if (curr->fCreateProc == createProc) {
     93             if (prev) {
     94                 prev->fNext = next;
     95             } else {
     96                 // we have a new head of our chain
     97                 SkTLS::PlatformSetSpecific(next);
     98             }
     99             delete curr;
    100             break;
    101         }
    102         prev = curr;
    103         curr = next;
    104     }
    105 }
    106