sharedobject.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // © 2016 and later: Unicode, Inc. and others.
  2. // License & terms of use: http://www.unicode.org/copyright.html
  3. /*
  4. ******************************************************************************
  5. * Copyright (C) 2015-2016, International Business Machines
  6. * Corporation and others. All Rights Reserved.
  7. ******************************************************************************
  8. * sharedobject.h
  9. */
  10. #ifndef __SHAREDOBJECT_H__
  11. #define __SHAREDOBJECT_H__
  12. #include "unicode/uobject.h"
  13. #include "umutex.h"
  14. U_NAMESPACE_BEGIN
  15. class SharedObject;
  16. /**
  17. * Base class for unified cache exposing enough methods to SharedObject
  18. * instances to allow their addRef() and removeRef() methods to
  19. * update cache metrics. No other part of ICU, except for SharedObject,
  20. * should directly call the methods of this base class.
  21. */
  22. class U_COMMON_API UnifiedCacheBase : public UObject {
  23. public:
  24. UnifiedCacheBase() { }
  25. /**
  26. * Notify the cache implementation that an object was seen transitioning to
  27. * zero hard references. The cache may use this to keep track the number of
  28. * unreferenced SharedObjects, and to trigger evictions.
  29. */
  30. virtual void handleUnreferencedObject() const = 0;
  31. virtual ~UnifiedCacheBase();
  32. private:
  33. UnifiedCacheBase(const UnifiedCacheBase &) = delete;
  34. UnifiedCacheBase &operator=(const UnifiedCacheBase &) = delete;
  35. };
  36. /**
  37. * Base class for shared, reference-counted, auto-deleted objects.
  38. * Subclasses can be immutable.
  39. * If they are mutable, then they must implement their copy constructor
  40. * so that copyOnWrite() works.
  41. *
  42. * Either stack-allocate, use LocalPointer, or use addRef()/removeRef().
  43. * Sharing requires reference-counting.
  44. */
  45. class U_COMMON_API SharedObject : public UObject {
  46. public:
  47. /** Initializes totalRefCount, softRefCount to 0. */
  48. SharedObject() :
  49. softRefCount(0),
  50. hardRefCount(0),
  51. cachePtr(nullptr) {}
  52. /** Initializes totalRefCount, softRefCount to 0. */
  53. SharedObject(const SharedObject &other) :
  54. UObject(other),
  55. softRefCount(0),
  56. hardRefCount(0),
  57. cachePtr(nullptr) {}
  58. virtual ~SharedObject();
  59. /**
  60. * Increments the number of hard references to this object. Thread-safe.
  61. * Not for use from within the Unified Cache implementation.
  62. */
  63. void addRef() const;
  64. /**
  65. * Decrements the number of hard references to this object, and
  66. * arrange for possible cache-eviction and/or deletion if ref
  67. * count goes to zero. Thread-safe.
  68. *
  69. * Not for use from within the UnifiedCache implementation.
  70. */
  71. void removeRef() const;
  72. /**
  73. * Returns the number of hard references for this object.
  74. * Uses a memory barrier.
  75. */
  76. int32_t getRefCount() const;
  77. /**
  78. * If noHardReferences() == true then this object has no hard references.
  79. * Must be called only from within the internals of UnifiedCache.
  80. */
  81. inline UBool noHardReferences() const { return getRefCount() == 0; }
  82. /**
  83. * If hasHardReferences() == true then this object has hard references.
  84. * Must be called only from within the internals of UnifiedCache.
  85. */
  86. inline UBool hasHardReferences() const { return getRefCount() != 0; }
  87. /**
  88. * Deletes this object if it has no references.
  89. * Available for non-cached SharedObjects only. Ownership of cached objects
  90. * is with the UnifiedCache, which is solely responsible for eviction and deletion.
  91. */
  92. void deleteIfZeroRefCount() const;
  93. /**
  94. * Returns a writable version of ptr.
  95. * If there is exactly one owner, then ptr itself is returned as a
  96. * non-const pointer.
  97. * If there are multiple owners, then ptr is replaced with a
  98. * copy-constructed clone,
  99. * and that is returned.
  100. * Returns nullptr if cloning failed.
  101. *
  102. * T must be a subclass of SharedObject.
  103. */
  104. template<typename T>
  105. static T *copyOnWrite(const T *&ptr) {
  106. const T *p = ptr;
  107. if(p->getRefCount() <= 1) { return const_cast<T *>(p); }
  108. T *p2 = new T(*p);
  109. if(p2 == nullptr) { return nullptr; }
  110. p->removeRef();
  111. ptr = p2;
  112. p2->addRef();
  113. return p2;
  114. }
  115. /**
  116. * Makes dest an owner of the object pointed to by src while adjusting
  117. * reference counts and deleting the previous object dest pointed to
  118. * if necessary. Before this call is made, dest must either be nullptr or
  119. * be included in the reference count of the object it points to.
  120. *
  121. * T must be a subclass of SharedObject.
  122. */
  123. template<typename T>
  124. static void copyPtr(const T *src, const T *&dest) {
  125. if(src != dest) {
  126. if(dest != nullptr) { dest->removeRef(); }
  127. dest = src;
  128. if(src != nullptr) { src->addRef(); }
  129. }
  130. }
  131. /**
  132. * Equivalent to copyPtr(nullptr, dest).
  133. */
  134. template<typename T>
  135. static void clearPtr(const T *&ptr) {
  136. if (ptr != nullptr) {
  137. ptr->removeRef();
  138. ptr = nullptr;
  139. }
  140. }
  141. private:
  142. /**
  143. * The number of references from the UnifiedCache, which is
  144. * the number of times that the sharedObject is stored as a hash table value.
  145. * For use by UnifiedCache implementation code only.
  146. * All access is synchronized by UnifiedCache's gCacheMutex
  147. */
  148. mutable int32_t softRefCount;
  149. friend class UnifiedCache;
  150. /**
  151. * Reference count, excluding references from within the UnifiedCache implementation.
  152. */
  153. mutable u_atomic_int32_t hardRefCount;
  154. mutable const UnifiedCacheBase *cachePtr;
  155. };
  156. U_NAMESPACE_END
  157. #endif