From 46f20e19a343ad0fa17dde6c32f17e60fc682c9b Mon Sep 17 00:00:00 2001 From: Manuel Nickschas Date: Tue, 1 Nov 2016 17:23:44 +0100 Subject: [PATCH] common: Add Deferred{Unique|Shared}Ptr and helpers This commit adds smart pointers for holding QObject derivatives. On destruction, they will deleteLater() the object they're holding. This is the recommended and safe way for deleting QObject instances. Be careful with using such smart pointers outside of the scope of their parent, for objects that are owned. The parent will delete its children, and any outside reference still held by a smart pointer will lead to a double free! --- src/common/deferredptr.h | 99 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/common/deferredptr.h diff --git a/src/common/deferredptr.h b/src/common/deferredptr.h new file mode 100644 index 00000000..1ea1f6b4 --- /dev/null +++ b/src/common/deferredptr.h @@ -0,0 +1,99 @@ +/*************************************************************************** + * Copyright (C) 2005-2016 by the Quassel Project * + * devel@quassel-irc.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) version 3. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#pragma once + +#include +#include + +#include + +namespace detail { + +/** + * Deleter for storing QObjects in STL containers and smart pointers + * + * QObject should always be deleted by calling deleteLater() on them, so the event loop can + * perform necessary cleanups. + */ +struct DeferredDeleter { + /// Deletes the given QObject + void operator()(QObject *object) const { + if (object) + object->deleteLater(); + } +}; + +} // detail + +/** + * Unique pointer for QObjects with deferred deletion + * + * @tparam T Type derived from QObject + */ +template +using DeferredUniquePtr = std::unique_ptr; + + +/** + * Helper function for creating a DeferredUniquePtr + * + * An instance of T is created and returned in a DeferredUniquePtr, such that it will be deleted via + * QObject::deleteLater(). + * + * @tparam T The type to create + * @tparam Args Constructor argument types + * @param[in] args Constructor arguments + * @returns A DeferredUniquePtr holding a new instance of T + */ +template +DeferredUniquePtr makeDeferredUnique(Args... args) +{ + static_assert(std::is_base_of::value, "Type must inherit from QObject"); + return DeferredUniquePtr(new T(std::forward(args)...)); +} + + +/** + * Shared pointer for QObjects with deferred deletion + * + * @tparam T Type derived from QObject + */ +template +using DeferredSharedPtr = std::shared_ptr; + + +/** + * Helper function for creating a DeferredSharedPtr + * + * An instance of T is created and returned in a DeferredSharedPtr, such that it will be deleted via + * QObject::deleteLater(). + * + * @tparam T The type to create + * @tparam Args Constructor argument types + * @param[in] args Constructor arguments + * @returns A DeferredSharedPtr holding a new instance of T + */ +template +DeferredSharedPtr makeDeferredShared(Args... args) +{ + static_assert(std::is_base_of::value, "Type must inherit from QObject"); + return DeferredSharedPtr(new T(std::forward(args)...), detail::DeferredDeleter{}); +} -- 2.20.1