1ef4579cda09b73e3d4d98af48201da25adc29326Larisse Voufo//
22f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor//  SkTLS.h
32f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor//
42f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor//
52f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor//  Created by Mike Reed on 4/21/12.
62def48394f6d48bde0dec2b514193c2b533265b5Douglas Gregor//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
72def48394f6d48bde0dec2b514193c2b533265b5Douglas Gregor//
82def48394f6d48bde0dec2b514193c2b533265b5Douglas Gregor
92def48394f6d48bde0dec2b514193c2b533265b5Douglas Gregor#ifndef SkTLS_DEFINED
102def48394f6d48bde0dec2b514193c2b533265b5Douglas Gregor#define SkTLS_DEFINED
112def48394f6d48bde0dec2b514193c2b533265b5Douglas Gregor
12578b69b186d9cba0a6ae1dd7f4c04cd6a49f0aacJohn McCall#include "SkTypes.h"
132def48394f6d48bde0dec2b514193c2b533265b5Douglas Gregor
144cde94a04694d5d24dc9e3bf6c5fa3403629838eEli Friedman/**
154cde94a04694d5d24dc9e3bf6c5fa3403629838eEli Friedman *  Maintains a per-thread cache, using a CreateProc as the key into that cache.
162f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor */
172f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregorclass SkTLS {
182f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregorpublic:
192f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor    typedef void* (*CreateProc)();
2010bd36882406cdf4805e35add1ce2f11ab9ae152Douglas Gregor    typedef void  (*DeleteProc)(void*);
2110bd36882406cdf4805e35add1ce2f11ab9ae152Douglas Gregor
222f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor    /**
232f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor     *  If Get() has previously been called with this CreateProc, then this
242f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor     *  returns its cached data, otherwise it returns NULL. The CreateProc is
252f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor     *  never invoked in Find, it is only used as a key for searching the
262f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor     *  cache.
272f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor     */
286e4750188e836e119f8605cbd34023d0a3b18011Chris Lattner    static void* Find(CreateProc);
296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    /**
316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines     *  Return the cached data that was returned by the CreateProc. This proc
326e4750188e836e119f8605cbd34023d0a3b18011Chris Lattner     *  is only called the first time Get is called, and there after it is
336e4750188e836e119f8605cbd34023d0a3b18011Chris Lattner     *  cached (per-thread), using the CreateProc as a key to look it up.
346e4750188e836e119f8605cbd34023d0a3b18011Chris Lattner     *
356e4750188e836e119f8605cbd34023d0a3b18011Chris Lattner     *  When this thread, or Delete is called, the cached data is removed, and
362f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor     *  if a DeleteProc was specified, it is passed the pointer to the cached
372f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor     *  data.
382f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor     */
392f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor    static void* Get(CreateProc, DeleteProc);
402f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor
412f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor    /**
422f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor     *  Remove (optionally calling the DeleteProc if it was specificed in Get)
432f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor     *  the cached data associated with this CreateProc. If no associated cached
442f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor     *  data is found, do nothing.
455f4a6829dc58cab2f76e2b98492859aa3b91e3f2Chris Lattner     */
465f4a6829dc58cab2f76e2b98492859aa3b91e3f2Chris Lattner    static void Delete(CreateProc);
472f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor
482f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregorprivate:
492f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor    // Our implementation requires only 1 TLS slot, as we manage multiple values
502f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor    // ourselves in a list, with the platform specific value as our head.
512f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor
522f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor    /**
532f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor     *  Implemented by the platform, to return the value of our (one) slot per-thread
542f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor     *
552f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor     *  If forceCreateTheSlot is true, then we must have created the "slot" for
562f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor     *  our TLS, even though we know that the return value will be NULL in that
577c2342dd4c9947806842e5aca3d2bb2e542853c9John McCall     *  case (i.e. no-slot and first-time-slot both return NULL). This ensures
5858f9e13e87e57236fee4b914eea9be6f92a1c345Chris Lattner     *  that after calling GetSpecific, we know that we can legally call
597c2342dd4c9947806842e5aca3d2bb2e542853c9John McCall     *  SetSpecific.
602f1bc5285ccd40f411af5f5993f013e27e74ab78Douglas Gregor     *
613201f6beec688ab9fe8750527e28f52d5420e22dSebastian Redl     *  If forceCreateTheSlot is false, then the impl can either create the
623201f6beec688ab9fe8750527e28f52d5420e22dSebastian Redl     *  slot or not.
633201f6beec688ab9fe8750527e28f52d5420e22dSebastian Redl     */
64d1a272204cef9304df3930d94f66713b05db27d6Douglas Gregor    static void* PlatformGetSpecific(bool forceCreateTheSlot);
653201f6beec688ab9fe8750527e28f52d5420e22dSebastian Redl
66b1622a1fd7b7f4ab8d00d0183d17c90ad25c14e3John McCall    /**
673201f6beec688ab9fe8750527e28f52d5420e22dSebastian Redl     *  Implemented by the platform, to set the value for our (one) slot per-thread
683201f6beec688ab9fe8750527e28f52d5420e22dSebastian Redl     *
697abfbdbc97ad8e7f340789f751df1e32b10118b4Douglas Gregor     *  The implementation can rely on GetSpecific(true) having been previously
703201f6beec688ab9fe8750527e28f52d5420e22dSebastian Redl     *  called before SetSpecific is called.
717c2342dd4c9947806842e5aca3d2bb2e542853c9John McCall     */
722c59d3c19715cb318a0a5939c735b8345d14d281Anders Carlsson    static void  PlatformSetSpecific(void*);
732c59d3c19715cb318a0a5939c735b8345d14d281Anders Carlsson
742c59d3c19715cb318a0a5939c735b8345d14d281Anders Carlssonpublic:
752c59d3c19715cb318a0a5939c735b8345d14d281Anders Carlsson    /**
762c59d3c19715cb318a0a5939c735b8345d14d281Anders Carlsson     *  Will delete our internal list. To be called by the platform if/when its
772c59d3c19715cb318a0a5939c735b8345d14d281Anders Carlsson     *  TLS slot is deleted (often at thread shutdown).
782c59d3c19715cb318a0a5939c735b8345d14d281Anders Carlsson     *
792c59d3c19715cb318a0a5939c735b8345d14d281Anders Carlsson     *  Public *only* for the platform's use, not to be called by a client.
802c59d3c19715cb318a0a5939c735b8345d14d281Anders Carlsson     */
812c59d3c19715cb318a0a5939c735b8345d14d281Anders Carlsson    static void Destructor(void* ptr);
822c59d3c19715cb318a0a5939c735b8345d14d281Anders Carlsson};
83b191e2dda9f4dc033cb21f9625a78fe80d4ac105Fariborz Jahanian
84b191e2dda9f4dc033cb21f9625a78fe80d4ac105Fariborz Jahanian#endif
85b191e2dda9f4dc033cb21f9625a78fe80d4ac105Fariborz Jahanian