aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/core/SkRefCnt.h
diff options
context:
space:
mode:
authorGravatar reed <reed@google.com>2016-03-01 07:28:51 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2016-03-01 07:28:51 -0800
commitbb7b043b2db64197d2f6a1edaf3562a50c77afb1 (patch)
tree18d20cebb755cb2069732472529ac630d3641634 /include/core/SkRefCnt.h
parent856cc17db434be717a29e1fa893a2108d1f9db36 (diff)
isolate sk_sp from larger cl
Diffstat (limited to 'include/core/SkRefCnt.h')
-rw-r--r--include/core/SkRefCnt.h99
1 files changed, 99 insertions, 0 deletions
diff --git a/include/core/SkRefCnt.h b/include/core/SkRefCnt.h
index 9d1e5f1f02..43251d0788 100644
--- a/include/core/SkRefCnt.h
+++ b/include/core/SkRefCnt.h
@@ -227,4 +227,103 @@ private:
mutable int32_t fRefCnt;
};
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Shared pointer class to wrap classes that support a ref()/unref() interface.
+ *
+ * This can be used for classes inheriting from SkRefCnt, but it also works for other
+ * classes that match the interface, but have different internal choices: e.g. the hosted class
+ * may have its ref/unref be thread-safe, but that is not assumed/imposed by sk_sp.
+ */
+template <typename T> class sk_sp {
+public:
+ sk_sp() : fPtr(nullptr) {}
+ sk_sp(std::nullptr_t) : fPtr(nullptr) {}
+
+ /**
+ * Shares the underlying object by calling ref(), so that both the argument and the newly
+ * created sk_sp both have a reference to it.
+ */
+ sk_sp(const sk_sp<T>& that) : fPtr(SkSafeRef(that.get())) {}
+
+ /**
+ * Move the underlying object from the argument to the newly created sk_sp. Afterwards only
+ * the new sk_sp will have a reference to the object, and the argument will point to null.
+ * No call to ref() or unref() will be made.
+ */
+ sk_sp(sk_sp<T>&& that) : fPtr(that.release()) {}
+
+ /**
+ * Adopt the bare pointer into the newly created sk_sp.
+ * No call to ref() or unref() will be made.
+ */
+ explicit sk_sp(T* obj) : fPtr(obj) {}
+
+ /**
+ * Calls unref() on the underlying object pointer.
+ */
+ ~sk_sp() {
+ SkSafeUnref(fPtr);
+ }
+
+ sk_sp<T>& operator=(std::nullptr_t) { this->reset(); }
+
+ /**
+ * Shares the underlying object referenced by the argument by calling ref() on it. If this
+ * sk_sp previously had a reference to an object (i.e. not null) it will call unref() on that
+ * object.
+ */
+ sk_sp<T>& operator=(const sk_sp<T>& that) {
+ this->reset(SkSafeRef(that.get()));
+ return *this;
+ }
+
+ /**
+ * Move the underlying object from the argument to the sk_sp. If the sk_sp previously held
+ * a reference to another object, unref() will be called on that object. No call to ref()
+ * will be made.
+ */
+ sk_sp<T>& operator=(sk_sp<T>&& that) {
+ this->reset(that.release());
+ return *this;
+ }
+
+ bool operator==(std::nullptr_t) const { return this->get() == nullptr; }
+ bool operator!=(std::nullptr_t) const { return this->get() != nullptr; }
+
+ bool operator==(const sk_sp<T>& that) const { return this->get() == that.get(); }
+ bool operator!=(const sk_sp<T>& that) const { return this->get() != that.get(); }
+
+ explicit operator bool() const { return this->get() != nullptr; }
+
+ T* get() const { return fPtr; }
+ T* operator->() const { return fPtr; }
+
+ /**
+ * Adopt the new bare pointer, and call unref() on any previously held object (if not null).
+ * No call to ref() will be made.
+ */
+ void reset(T* ptr = nullptr) {
+ if (fPtr != ptr) {
+ SkSafeUnref(fPtr);
+ fPtr = ptr;
+ }
+ }
+
+ /**
+ * Return the bare pointer, and set the internal object pointer to nullptr.
+ * The caller must assume ownership of the object, and manage its reference count directly.
+ * No call to unref() will be made.
+ */
+ T* SK_WARN_UNUSED_RESULT release() {
+ T* ptr = fPtr;
+ fPtr = nullptr;
+ return ptr;
+ }
+
+private:
+ T* fPtr;
+};
+
#endif