Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkCachedData.h
1 /*
2  * Copyright 2014 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 SkCachedData_DEFINED
9 #define SkCachedData_DEFINED
10
11 #include "SkThread.h"
12
13 class SkDiscardableMemory;
14
15 class SkCachedData : ::SkNoncopyable {
16 public:
17     SkCachedData(void* mallocData, size_t size);
18     SkCachedData(size_t size, SkDiscardableMemory*);
19     virtual ~SkCachedData();
20
21     size_t size() const { return fSize; }
22     const void* data() const { return fData; }
23
24     void* writable_data() { return fData; }
25
26     void ref() const { this->internalRef(false); }
27     void unref() const { this->internalUnref(false); }
28
29     int testing_only_getRefCnt() const { return fRefCnt; }
30     bool testing_only_isLocked() const { return fIsLocked; }
31     bool testing_only_isInCache() const { return fInCache; }
32
33 protected:
34     // called when fData changes. could be NULL.
35     virtual void onDataChange(void* oldData, void* newData) {}
36
37 private:
38     SkMutex fMutex;     // could use a pool of these...
39
40     enum StorageType {
41         kDiscardableMemory_StorageType,
42         kMalloc_StorageType
43     };
44
45     union {
46         SkDiscardableMemory*    fDM;
47         void*                   fMalloc;
48     } fStorage;
49     void*       fData;
50     size_t      fSize;
51     int         fRefCnt;    // low-bit means we're owned by the cache
52     StorageType fStorageType;
53     bool        fInCache;
54     bool        fIsLocked;
55
56     void internalRef(bool fromCache) const;
57     void internalUnref(bool fromCache) const;
58
59     void inMutexRef(bool fromCache);
60     bool inMutexUnref(bool fromCache);  // returns true if we should delete "this"
61     void inMutexLock();
62     void inMutexUnlock();
63
64     // called whenever our fData might change (lock or unlock)
65     void setData(void* newData) {
66         if (newData != fData) {
67             // notify our subclasses of the change
68             this->onDataChange(fData, newData);
69             fData = newData;
70         }
71     }
72
73     class AutoMutexWritable;
74
75 public:
76 #ifdef SK_DEBUG
77     void validate() const;
78 #else
79     void validate() const {}
80 #endif
81     
82    /*
83      *  Attaching a data to to a SkResourceCache (only one at a time) enables the data to be
84      *  unlocked when the cache is the only owner, thus freeing it to be purged (assuming the
85      *  data is backed by a SkDiscardableMemory).
86      *
87      *  When attached, it also automatically attempts to "lock" the data when the first client
88      *  ref's the data (typically from a find(key, visitor) call).
89      *
90      *  Thus the data will always be "locked" when a non-cache has a ref on it (whether or not
91      *  the lock succeeded to recover the memory -- check data() to see if it is NULL).
92      */
93
94     /*
95      *  Call when adding this instance to a SkResourceCache::Rec subclass
96      *  (typically in the Rec's constructor).
97      */
98     void attachToCacheAndRef() const { this->internalRef(true); }
99
100     /*
101      *  Call when removing this instance from a SkResourceCache::Rec subclass
102      *  (typically in the Rec's destructor).
103      */
104     void detachFromCacheAndUnref() const { this->internalUnref(true); }
105 };
106
107 #endif