// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #ifndef QCOMTASKRESOURCE_P_H #define QCOMTASKRESOURCE_P_H #include #include #include #include #include class QEmptyDeleter final { public: template void operator()(T /*element*/) const { } }; class QComDeleter final { public: template void operator()(T element) const { element->Release(); } }; template class QComTaskResourceBase { public: QComTaskResourceBase(const QComTaskResourceBase &source) = delete; QComTaskResourceBase &operator=(const QComTaskResourceBase &right) = delete; explicit operator bool() const { return m_resource != nullptr; } T *get() const { return m_resource; } protected: QComTaskResourceBase() = default; explicit QComTaskResourceBase(T *const resource) : m_resource(resource) { } T *release() { return std::exchange(m_resource, nullptr); } void reset(T *const resource = nullptr) { if (m_resource != resource) { if (m_resource) CoTaskMemFree(m_resource); m_resource = resource; } } T *m_resource = nullptr; }; template class QComTaskResource final : public QComTaskResourceBase { using Base = QComTaskResourceBase; public: using Base::QComTaskResourceBase; ~QComTaskResource() { reset(); } T *operator->() const { return m_resource; } T &operator*() const { return *m_resource; } T **address() { Q_ASSERT(m_resource == nullptr); return &m_resource; } using Base::release; using Base::reset; private: using Base::m_resource; }; template class QComTaskResource final : public QComTaskResourceBase { using Base = QComTaskResourceBase; public: QComTaskResource() = default; explicit QComTaskResource(T *const resource, const std::size_t size) : Base(resource), m_size(size) { } ~QComTaskResource() { reset(); } T &operator[](const std::size_t index) const { Q_ASSERT(index < m_size); return m_resource[index]; } T *release() { m_size = 0; return Base::release(); } void reset() { reset(nullptr, 0); } void reset(T *const resource, const std::size_t size) { if (m_resource != resource) { resetElements(); Base::reset(resource); m_size = size; } } private: void resetElements() { if constexpr (!std::is_same_v) { std::for_each(m_resource, m_resource + m_size, TElementDeleter()); } } std::size_t m_size = 0; using Base::m_resource; }; #endif