// Copyright 2017 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef UI_BASE_GLIB_SCOPED_GOBJECT_H_ #define UI_BASE_GLIB_SCOPED_GOBJECT_H_ #include #include "base/check.h" #include "base/memory/raw_ptr.h" // Similar to a std::shared_ptr for GObject types. template class ScopedGObject { public: ScopedGObject() = default; ScopedGObject(const ScopedGObject& other) : obj_(other.obj_) { Ref(); } ScopedGObject(ScopedGObject&& other) : obj_(other.obj_) { other.obj_ = nullptr; } ~ScopedGObject() { Unref(); } ScopedGObject& operator=(const ScopedGObject& other) { Unref(); obj_ = other.obj_; Ref(); return *this; } ScopedGObject& operator=(ScopedGObject&& other) { Unref(); obj_ = other.obj_; other.obj_ = nullptr; return *this; } T* get() { return obj_; } operator T*() { return obj_; } private: template friend ScopedGObject TakeGObject(U* obj); template friend ScopedGObject WrapGObject(U* obj); explicit ScopedGObject(T* obj) : obj_(obj) {} void RefSink() { // Remove the floating reference from |obj_| if it has one. if (obj_ && g_object_is_floating(obj_)) g_object_ref_sink(obj_); } void Ref() { if (obj_) { DCHECK(!g_object_is_floating(obj_)); g_object_ref(obj_); } } // This function is necessary so that gtk can overload it in // the case of T = GtkStyleContext. void Unref() { if (obj_) g_object_unref(obj_); } raw_ptr obj_ = nullptr; }; // Create a ScopedGObject and do not increase the GObject's reference count. // This is usually used to reference a newly-created GObject, which are created // with a reference count of 1 by default. template ScopedGObject TakeGObject(T* obj) { ScopedGObject scoped(obj); scoped.RefSink(); return scoped; } // Create a ScopedGObject and increase the GObject's reference count by 1. // This is usually used to reference an existing GObject. template ScopedGObject WrapGObject(T* obj) { ScopedGObject scoped(obj); scoped.Ref(); return scoped; } #endif // UI_BASE_GLIB_SCOPED_GOBJECT_H_