SkCFObject.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*
  2. * Copyright 2019 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. #ifndef SkCFObject_DEFINED
  8. #define SkCFObject_DEFINED
  9. #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
  10. #import <CoreFoundation/CoreFoundation.h>
  11. /**
  12. * Wrapper class for managing lifetime of CoreFoundation objects. It will call
  13. * CFRetain and CFRelease appropriately on creation, assignment, and deletion.
  14. * Based on sk_sp<>.
  15. */
  16. template <typename T> static inline T SkCFSafeRetain(T obj) {
  17. if (obj) {
  18. CFRetain(obj);
  19. }
  20. return obj;
  21. }
  22. template <typename T> static inline void SkCFSafeRelease(T obj) {
  23. if (obj) {
  24. CFRelease(obj);
  25. }
  26. }
  27. template <typename T> class sk_cf_obj {
  28. public:
  29. using element_type = T;
  30. constexpr sk_cf_obj() : fObject(nullptr) {}
  31. /**
  32. * Shares the underlying object by calling CFRetain(), so that both the argument and the newly
  33. * created sk_cf_obj both have a reference to it.
  34. */
  35. sk_cf_obj(const sk_cf_obj<T>& that) : fObject(SkCFSafeRetain(that.get())) {}
  36. /**
  37. * Move the underlying object from the argument to the newly created sk_cf_obj. Afterwards only
  38. * the new sk_cf_obj will have a reference to the object, and the argument will point to null.
  39. * No call to CFRetain() or CFRelease() will be made.
  40. */
  41. sk_cf_obj(sk_cf_obj<T>&& that) : fObject(that.release()) {}
  42. /**
  43. * Adopt the bare object into the newly created sk_cf_obj.
  44. * No call to CFRetain() or CFRelease() will be made.
  45. */
  46. explicit sk_cf_obj(T obj) {
  47. fObject = obj;
  48. }
  49. /**
  50. * Calls CFRelease() on the underlying object pointer.
  51. */
  52. ~sk_cf_obj() {
  53. SkCFSafeRelease(fObject);
  54. SkDEBUGCODE(fObject = nullptr);
  55. }
  56. /**
  57. * Shares the underlying object referenced by the argument by calling CFRetain() on it. If this
  58. * sk_cf_obj previously had a reference to an object (i.e. not null) it will call CFRelease()
  59. * on that object.
  60. */
  61. sk_cf_obj<T>& operator=(const sk_cf_obj<T>& that) {
  62. if (this != &that) {
  63. this->reset(SkCFSafeRetain(that.get()));
  64. }
  65. return *this;
  66. }
  67. /**
  68. * Move the underlying object from the argument to the sk_cf_obj. If the sk_cf_obj
  69. * previously held a reference to another object, CFRelease() will be called on that object.
  70. * No call to CFRetain() will be made.
  71. */
  72. sk_cf_obj<T>& operator=(sk_cf_obj<T>&& that) {
  73. this->reset(that.release());
  74. return *this;
  75. }
  76. T get() const { return fObject; }
  77. /**
  78. * Adopt the new object, and call CFRelease() on any previously held object (if not null).
  79. * No call to CFRetain() will be made.
  80. */
  81. void reset(T object = nullptr) {
  82. T oldObject = fObject;
  83. fObject = object;
  84. SkCFSafeRelease(oldObject);
  85. }
  86. /**
  87. * Shares the new object by calling CFRetain() on it. If this sk_cf_obj previously had a
  88. * reference to an object (i.e. not null) it will call CFRelease() on that object.
  89. */
  90. void retain(T object) {
  91. if (this->fObject != object) {
  92. this->reset(SkCFSafeRetain(object));
  93. }
  94. }
  95. /**
  96. * Return the original object, and set the internal object to nullptr.
  97. * The caller must assume ownership of the object, and manage its reference count directly.
  98. * No call to CFRelease() will be made.
  99. */
  100. T SK_WARN_UNUSED_RESULT release() {
  101. T obj = fObject;
  102. fObject = nullptr;
  103. return obj;
  104. }
  105. private:
  106. T fObject;
  107. };
  108. template <typename T> inline bool operator==(const sk_cf_obj<T>& a,
  109. const sk_cf_obj<T>& b) {
  110. return a.get() == b.get();
  111. }
  112. template <typename T> inline bool operator!=(const sk_cf_obj<T>& a,
  113. const sk_cf_obj<T>& b) {
  114. return a.get() != b.get();
  115. }
  116. #endif // SK_BUILD_FOR_MAC || SK_BUILD_FOR_IOS
  117. #endif // SkCFOBject_DEFINED