// 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 #include "base/check.h" #include "base/memory/raw_ptr.h" // Similar to a scoped_refptr for GObject types. template class ScopedGObject { public: ScopedGObject() = default; // Deliberately implicit to allow returning nullptrs. // NOLINTNEXTLINE(google-explicit-constructor) ScopedGObject(std::nullptr_t ptr) {} ScopedGObject(const ScopedGObject& other) : obj_(other.obj_) { Ref(); } ScopedGObject(ScopedGObject&& other) : obj_(other.obj_) { other.obj_ = nullptr; } ~ScopedGObject() { Reset(); } ScopedGObject& operator=(const ScopedGObject& other) { Reset(); obj_ = other.obj_; Ref(); return *this; } ScopedGObject& operator=(ScopedGObject&& other) { Reset(); obj_ = other.obj_; other.obj_ = nullptr; return *this; } void Reset() { if (obj_) { g_object_unref(obj_.ExtractAsDangling()); } } T* get() { return obj_; } // Deliberately implicit to allow easier interaction with C APIs. // NOLINTNEXTLINE(google-explicit-constructor) 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_); } } 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_