SkCachedData.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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. #include "include/private/SkMalloc.h"
  8. #include "src/core/SkCachedData.h"
  9. #include "src/core/SkDiscardableMemory.h"
  10. SkCachedData::SkCachedData(void* data, size_t size)
  11. : fData(data)
  12. , fSize(size)
  13. , fRefCnt(1)
  14. , fStorageType(kMalloc_StorageType)
  15. , fInCache(false)
  16. , fIsLocked(true)
  17. {
  18. fStorage.fMalloc = data;
  19. }
  20. SkCachedData::SkCachedData(size_t size, SkDiscardableMemory* dm)
  21. : fData(dm->data())
  22. , fSize(size)
  23. , fRefCnt(1)
  24. , fStorageType(kDiscardableMemory_StorageType)
  25. , fInCache(false)
  26. , fIsLocked(true)
  27. {
  28. fStorage.fDM = dm;
  29. }
  30. SkCachedData::~SkCachedData() {
  31. switch (fStorageType) {
  32. case kMalloc_StorageType:
  33. sk_free(fStorage.fMalloc);
  34. break;
  35. case kDiscardableMemory_StorageType:
  36. delete fStorage.fDM;
  37. break;
  38. }
  39. }
  40. class SkCachedData::AutoMutexWritable {
  41. public:
  42. AutoMutexWritable(const SkCachedData* cd) : fCD(const_cast<SkCachedData*>(cd)) {
  43. fCD->fMutex.acquire();
  44. fCD->validate();
  45. }
  46. ~AutoMutexWritable() {
  47. fCD->validate();
  48. fCD->fMutex.release();
  49. }
  50. SkCachedData* get() { return fCD; }
  51. SkCachedData* operator->() { return fCD; }
  52. private:
  53. SkCachedData* fCD;
  54. };
  55. void SkCachedData::internalRef(bool fromCache) const {
  56. AutoMutexWritable(this)->inMutexRef(fromCache);
  57. }
  58. void SkCachedData::internalUnref(bool fromCache) const {
  59. if (AutoMutexWritable(this)->inMutexUnref(fromCache)) {
  60. // can't delete inside doInternalUnref, since it is locking a mutex (which we own)
  61. delete this;
  62. }
  63. }
  64. ///////////////////////////////////////////////////////////////////////////////////////////////////
  65. void SkCachedData::inMutexRef(bool fromCache) {
  66. if ((1 == fRefCnt) && fInCache) {
  67. this->inMutexLock();
  68. }
  69. fRefCnt += 1;
  70. if (fromCache) {
  71. SkASSERT(!fInCache);
  72. fInCache = true;
  73. }
  74. }
  75. bool SkCachedData::inMutexUnref(bool fromCache) {
  76. switch (--fRefCnt) {
  77. case 0:
  78. // we're going to be deleted, so we need to be unlocked (for DiscardableMemory)
  79. if (fIsLocked) {
  80. this->inMutexUnlock();
  81. }
  82. break;
  83. case 1:
  84. if (fInCache && !fromCache) {
  85. // If we're down to 1 owner, and that owner is the cache, this it is safe
  86. // to unlock (and mutate fData) even if the cache is in a different thread,
  87. // as the cache is NOT allowed to inspect or use fData.
  88. this->inMutexUnlock();
  89. }
  90. break;
  91. default:
  92. break;
  93. }
  94. if (fromCache) {
  95. SkASSERT(fInCache);
  96. fInCache = false;
  97. }
  98. // return true when we need to be deleted
  99. return 0 == fRefCnt;
  100. }
  101. void SkCachedData::inMutexLock() {
  102. fMutex.assertHeld();
  103. SkASSERT(!fIsLocked);
  104. fIsLocked = true;
  105. switch (fStorageType) {
  106. case kMalloc_StorageType:
  107. this->setData(fStorage.fMalloc);
  108. break;
  109. case kDiscardableMemory_StorageType:
  110. if (fStorage.fDM->lock()) {
  111. void* ptr = fStorage.fDM->data();
  112. SkASSERT(ptr);
  113. this->setData(ptr);
  114. } else {
  115. this->setData(nullptr); // signal failure to lock, contents are gone
  116. }
  117. break;
  118. }
  119. }
  120. void SkCachedData::inMutexUnlock() {
  121. fMutex.assertHeld();
  122. SkASSERT(fIsLocked);
  123. fIsLocked = false;
  124. switch (fStorageType) {
  125. case kMalloc_StorageType:
  126. // nothing to do/check
  127. break;
  128. case kDiscardableMemory_StorageType:
  129. if (fData) { // did the previous lock succeed?
  130. fStorage.fDM->unlock();
  131. }
  132. break;
  133. }
  134. this->setData(nullptr); // signal that we're in an unlocked state
  135. }
  136. ///////////////////////////////////////////////////////////////////////////////////////////////////
  137. #ifdef SK_DEBUG
  138. void SkCachedData::validate() const {
  139. if (fIsLocked) {
  140. SkASSERT((fInCache && fRefCnt > 1) || !fInCache);
  141. switch (fStorageType) {
  142. case kMalloc_StorageType:
  143. SkASSERT(fData == fStorage.fMalloc);
  144. break;
  145. case kDiscardableMemory_StorageType:
  146. // fData can be null or the actual value, depending if DM's lock succeeded
  147. break;
  148. }
  149. } else {
  150. SkASSERT((fInCache && 1 == fRefCnt) || (0 == fRefCnt));
  151. SkASSERT(nullptr == fData);
  152. }
  153. }
  154. #endif