Coverage Report

Created: 2026-09-17 06:53

src/zserio/UniquePtr.h
Line
Count
Source
1
#ifndef ZSERIO_UNIQUE_PTR_H_INC
2
#define ZSERIO_UNIQUE_PTR_H_INC
3
4
#include <memory>
5
#include <type_traits>
6
7
#include "zserio/AllocatorHolder.h"
8
#include "zserio/RebindAlloc.h"
9
10
namespace zserio
11
{
12
13
namespace detail
14
{
15
16
/**
17
 * Custom deleter to ensure proper deallocation of the unique_ptr.
18
 */
19
template <class ALLOC_T>
20
struct UniquePtrDeleter : public AllocatorHolder<ALLOC_T>
21
{
22
    using allocator_type = ALLOC_T;
23
    using T = typename allocator_type::value_type;
24
25
    /** Method generated by default. */
26
    /** \{ */
27
242
    ~UniquePtrDeleter() = default;
28
29
124
    UniquePtrDeleter(UniquePtrDeleter&& other) = default;
30
17
    UniquePtrDeleter& operator=(UniquePtrDeleter&& other) = default;
31
    /**
32
     * \}
33
     */
34
35
    /**
36
     * Copying is disallowed!
37
     * \{
38
     */
39
    UniquePtrDeleter(const UniquePtrDeleter& other) = delete;
40
    UniquePtrDeleter& operator=(const UniquePtrDeleter& other) = delete;
41
    /**
42
     * \}
43
     */
44
45
    /**
46
     * Empty constructor.
47
     */
48
    template <typename ALLOC_U = ALLOC_T>
49
    UniquePtrDeleter() :
50
            UniquePtrDeleter(ALLOC_U())
51
    {}
52
53
    /**
54
     * Constructor from given allocator.
55
     */
56
    template <typename ALLOC_U = ALLOC_T>
57
    UniquePtrDeleter(const ALLOC_U& allocator) :
58
            AllocatorHolder<ALLOC_T>(allocator)
59
118
    {
60
118
        static_assert(std::is_same<allocator_type, RebindAlloc<ALLOC_U, T>>::value,
61
118
                "UniquePtrDeleter requires same allocator in constructor!");
62
118
    }
63
64
    /**
65
     * DISABLED - Constructor from deleter to another type.
66
     *
67
     * This was originally used in JsonReader to cast polymorphic
68
     * types but it leads to only releasing memory of the base class and
69
     * it is correctly flagged by ASAN in clang-21. For polymorphic types
70
     * use std::shared_ptr.
71
     */
72
    template <typename ALLOC_U>
73
    UniquePtrDeleter(const UniquePtrDeleter<ALLOC_U>& deleter) = delete;
74
75
    void operator()(T* ptr)
76
63
    {
77
63
        allocator_type alloc = this->get_allocator();
78
63
        using AllocTraits = std::allocator_traits<allocator_type>;
79
63
        AllocTraits::destroy(alloc, std::addressof(*ptr));
80
63
        AllocTraits::deallocate(alloc, ptr, 1);
81
63
    }
82
};
83
84
} // namespace detail
85
86
/**
87
 * Typedef to std::unique_ptr provided for convenience - using std::allocator.
88
 *
89
 * Uses custom deleter to ensure proper deallocation.
90
 */
91
template <typename T, typename ALLOC = std::allocator<T>>
92
using unique_ptr = std::unique_ptr<T, detail::UniquePtrDeleter<ALLOC>>;
93
94
/**
95
 * Allocates memory for an object of type T using given allocator and constructs it passing args to its
96
 * constructor.
97
 *
98
 * \param allocator Allocator to use.
99
 * \param args      List of elements passed to T's constructor.
100
 *
101
 * \return Object of type zserio::unique_ptr<T, ALLOC> that owns and stores a pointer to the constructed object.
102
 */
103
template <typename T, typename ALLOC, class... Args>
104
zserio::unique_ptr<T, RebindAlloc<ALLOC, T>> allocate_unique(const ALLOC& allocator, Args&&... args)
105
64
{
106
64
    using Allocator = RebindAlloc<ALLOC, T>;
107
64
    using AllocTraits = std::allocator_traits<Allocator>;
108
109
64
    Allocator typedAllocator = allocator;
110
64
    typename AllocTraits::pointer ptr = AllocTraits::allocate(typedAllocator, 1);
111
64
    try
112
64
    {
113
64
        AllocTraits::construct(typedAllocator, std::addressof(*ptr), std::forward<Args>(args)...);
114
64
        return zserio::unique_ptr<T, Allocator>(std::addressof(*ptr), typedAllocator);
115
64
    }
116
64
    catch (...)
117
64
    {
118
1
        AllocTraits::deallocate(typedAllocator, ptr, 1);
119
1
        throw;
120
1
    }
121
64
}
122
123
} // namespace zserio
124
125
#endif // ZSERIO_UNIQUE_PTR_H_INC