.. _program_listing_file_nvcv_types_include_nvcv_HandleWrapper.hpp: Program Listing for File HandleWrapper.hpp ========================================== |exhale_lsh| :ref:`Return to documentation for file ` (``nvcv_types/include/nvcv/HandleWrapper.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp /* * SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef NVCV_HANDLE_WRAPPER_HPP #define NVCV_HANDLE_WRAPPER_HPP #include "detail/CheckError.hpp" #include "detail/CompilerUtils.h" #include #include namespace nvcv { template int HandleDecRef(HandleType handle); template int HandleIncRef(HandleType handle); template int HandleRefCount(HandleType handle); template void HandleDestroy(HandleType handle); template constexpr HandleType NullHandle() { return {}; } template constexpr bool HandleIsNull(HandleType h) { return h == NullHandle(); } namespace detail { template struct SharedHandleOps { static int DecRef(HandleType handle) { return HandleDecRef(handle); } static int IncRef(HandleType handle) { return HandleIncRef(handle); } static int RefCount(HandleType handle) { return HandleRefCount(handle); } static constexpr bool IsNull(HandleType handle) { return HandleIsNull(handle); } static constexpr HandleType Null() { return NullHandle(); }; }; template struct UniqueHandleOps { static void Destroy(HandleType handle) { HandleDestroy(handle); } static constexpr bool IsNull(HandleType handle) { return HandleIsNull(handle); } static constexpr HandleType Null() { return NullHandle(); }; }; } // namespace detail template> class UniqueHandle { public: ~UniqueHandle() { reset(); } explicit UniqueHandle(HandleType &&handle) : m_handle(handle) { handle = HandleOps::Null(); } UniqueHandle() = default; UniqueHandle(const UniqueHandle &other) = delete; UniqueHandle(UniqueHandle &&other) : m_handle(std::move(other.m_handle)) { other.m_handle = HandleOps::Null(); } UniqueHandle &operator=(UniqueHandle &&other) { if (&other == this) return *this; // avoid self-reset in self-move swap(other); other.reset(); return *this; } void swap(UniqueHandle &other) noexcept { std::swap(m_handle, other.m_handle); } void reset(HandleType &&handle = HandleOps::Null()) { assert(HandleOps::IsNull(handle) || handle != m_handle); if (*this) { HandleOps::Destroy(m_handle); } m_handle = std::move(handle); handle = HandleOps::Null(); } NVCV_NODISCARD HandleType release() noexcept { HandleType h = std::move(m_handle); m_handle = HandleOps::Null(); return h; } constexpr const HandleType get() const noexcept { return m_handle; } constexpr bool empty() const noexcept { return HandleOps::IsNull(m_handle); } constexpr explicit operator bool() const noexcept { return !empty(); } bool operator==(const UniqueHandle &other) const { return m_handle == other.m_handle; } bool operator!=(const UniqueHandle &other) const { return m_handle != other.m_handle; } private: HandleType m_handle = HandleOps::Null(); }; template> class SharedHandle { public: ~SharedHandle() { reset(); } SharedHandle() = default; explicit SharedHandle(HandleType &&handle) noexcept : m_handle(handle) { handle = HandleOps::Null(); } SharedHandle(SharedHandle &&other) noexcept : m_handle(std::move(other.m_handle)) { other.m_handle = HandleOps::Null(); } SharedHandle(const SharedHandle &other) { *this = other; } SharedHandle &operator=(SharedHandle &&other) { if (&other == this) return *this; // we must not reset the "other" in case of self-move swap(other); other.reset(); return *this; } SharedHandle &operator=(const SharedHandle &other) { HandleType new_handle = other.get(); if (m_handle == new_handle) return *this; if (!HandleOps::IsNull(new_handle)) HandleOps::IncRef(new_handle); reset(std::move(new_handle)); return *this; } void swap(SharedHandle &other) noexcept { std::swap(m_handle, other.m_handle); } int reset(HandleType &&handle = HandleOps::Null()) { auto old = m_handle; m_handle = std::move(handle); handle = HandleOps::Null(); if (!HandleOps::IsNull(old)) return HandleOps::DecRef(old); return 0; } NVCV_NODISCARD HandleType release() noexcept { HandleType h = std::move(m_handle); m_handle = HandleOps::Null(); return h; } constexpr const HandleType get() const noexcept { return m_handle; } int refCount() const noexcept { HandleType h = m_handle; return HandleOps::IsNull(h) ? 0 : HandleOps::RefCount(h); } constexpr bool empty() const noexcept { return HandleOps::IsNull(m_handle); } constexpr explicit operator bool() const noexcept { return !empty(); } bool operator==(const SharedHandle &other) const { return m_handle == other.m_handle; } bool operator!=(const SharedHandle &other) const { return m_handle != other.m_handle; } private: HandleType m_handle = HandleOps::Null(); }; #define NVCV_IMPL_DEC_REF(ObjectKind) \ template<> \ inline int HandleDecRef(NVCV##ObjectKind##Handle h) \ { \ int ref = -1; \ nvcv::detail::CheckThrow(nvcv##ObjectKind##DecRef(h, &ref)); \ return ref; \ } #define NVCV_IMPL_INC_REF(ObjectKind) \ template<> \ inline int HandleIncRef(NVCV##ObjectKind##Handle h) \ { \ int ref = -1; \ nvcv::detail::CheckThrow(nvcv##ObjectKind##IncRef(h, &ref)); \ return ref; \ } #define NVCV_IMPL_REF_COUNT(ObjectKind) \ template<> \ inline int HandleRefCount(NVCV##ObjectKind##Handle h) \ { \ int ref = -1; \ nvcv::detail::CheckThrow(nvcv##ObjectKind##RefCount(h, &ref)); \ return ref; \ } #define NVCV_IMPL_SHARED_HANDLE(ObjectKind) \ NVCV_IMPL_DEC_REF(ObjectKind) \ NVCV_IMPL_INC_REF(ObjectKind) \ NVCV_IMPL_REF_COUNT(ObjectKind) #define NVCV_IMPL_DESTROY(ObjectKind) \ template<> \ inline void HandleDestroy(NVCV##ObjectKind##Handle h) \ { \ nvcv::detail::CheckThrow(nvcv##ObjectKind##Destroy(h)); \ } #define NVCV_IMPL_DESTROY_VOID(ObjectKind) \ template<> \ inline void HandleDestroy(NVCV##ObjectKind##Handle h) \ { \ nvcv##ObjectKind##Destroy(h); \ } } // namespace nvcv #endif