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#ifndef SkTLS_DEFINED
9#define SkTLS_DEFINED
10
11#include "SkTypes.h"
12
13/**
14 *  Maintains a per-thread cache, using a CreateProc as the key into that cache.
15 */
16class SkTLS {
17public:
18    typedef void* (*CreateProc)();
19    typedef void  (*DeleteProc)(void*);
20
21    /**
22     *  If Get() has previously been called with this CreateProc, then this
23     *  returns its cached data, otherwise it returns NULL. The CreateProc is
24     *  never invoked in Find, it is only used as a key for searching the
25     *  cache.
26     */
27    static void* Find(CreateProc);
28
29    /**
30     *  Return the cached data that was returned by the CreateProc. This proc
31     *  is only called the first time Get is called, and there after it is
32     *  cached (per-thread), using the CreateProc as a key to look it up.
33     *
34     *  When this thread, or Delete is called, the cached data is removed, and
35     *  if a DeleteProc was specified, it is passed the pointer to the cached
36     *  data.
37     */
38    static void* Get(CreateProc, DeleteProc);
39
40    /**
41     *  Remove (optionally calling the DeleteProc if it was specificed in Get)
42     *  the cached data associated with this CreateProc. If no associated cached
43     *  data is found, do nothing.
44     */
45    static void Delete(CreateProc);
46
47private:
48    // Our implementation requires only 1 TLS slot, as we manage multiple values
49    // ourselves in a list, with the platform specific value as our head.
50
51    /**
52     *  Implemented by the platform, to return the value of our (one) slot per-thread
53     *
54     *  If forceCreateTheSlot is true, then we must have created the "slot" for
55     *  our TLS, even though we know that the return value will be NULL in that
56     *  case (i.e. no-slot and first-time-slot both return NULL). This ensures
57     *  that after calling GetSpecific, we know that we can legally call
58     *  SetSpecific.
59     *
60     *  If forceCreateTheSlot is false, then the impl can either create the
61     *  slot or not.
62     */
63    static void* PlatformGetSpecific(bool forceCreateTheSlot);
64
65    /**
66     *  Implemented by the platform, to set the value for our (one) slot per-thread
67     *
68     *  The implementation can rely on GetSpecific(true) having been previously
69     *  called before SetSpecific is called.
70     */
71    static void  PlatformSetSpecific(void*);
72
73public:
74    /**
75     *  Will delete our internal list. To be called by the platform if/when its
76     *  TLS slot is deleted (often at thread shutdown).
77     *
78     *  Public *only* for the platform's use, not to be called by a client.
79     */
80    static void Destructor(void* ptr);
81};
82
83#endif
84