1#pragma once
2
3#include "duckdb/common/exception.hpp"
4#include "duckdb/common/likely.hpp"
5#include "duckdb/common/memory_safety.hpp"
6
7#include <memory>
8#include <type_traits>
9
10namespace duckdb {
11
12template <class _Tp, class _Dp = std::default_delete<_Tp>, bool SAFE = true>
13class unique_ptr : public std::unique_ptr<_Tp, _Dp> {
14public:
15 using original = std::unique_ptr<_Tp, _Dp>;
16 using original::original;
17
18private:
19 static inline void AssertNotNull(const bool null) {
20#if defined(DUCKDB_DEBUG_NO_SAFETY) || defined(DUCKDB_CLANG_TIDY)
21 return;
22#else
23 if (DUCKDB_UNLIKELY(null)) {
24 throw duckdb::InternalException("Attempted to dereference unique_ptr that is NULL!");
25 }
26#endif
27 }
28
29public:
30 typename std::add_lvalue_reference<_Tp>::type operator*() const {
31 const auto ptr = original::get();
32 if (MemorySafety<SAFE>::enabled) {
33 AssertNotNull(null: !ptr);
34 }
35 return *ptr;
36 }
37
38 typename original::pointer operator->() const {
39 const auto ptr = original::get();
40 if (MemorySafety<SAFE>::enabled) {
41 AssertNotNull(null: !ptr);
42 }
43 return ptr;
44 }
45
46#ifdef DUCKDB_CLANG_TIDY
47 // This is necessary to tell clang-tidy that it reinitializes the variable after a move
48 [[clang::reinitializes]]
49#endif
50 inline void
51 reset(typename original::pointer ptr = typename original::pointer()) noexcept {
52 original::reset(ptr);
53 }
54};
55
56template <class _Tp, class _Dp, bool SAFE>
57class unique_ptr<_Tp[], _Dp, SAFE> : public std::unique_ptr<_Tp[], std::default_delete<_Tp[]>> {
58public:
59 using original = std::unique_ptr<_Tp[], std::default_delete<_Tp[]>>;
60 using original::original;
61
62private:
63 static inline void AssertNotNull(const bool null) {
64#if defined(DUCKDB_DEBUG_NO_SAFETY) || defined(DUCKDB_CLANG_TIDY)
65 return;
66#else
67 if (DUCKDB_UNLIKELY(null)) {
68 throw duckdb::InternalException("Attempted to dereference unique_ptr that is NULL!");
69 }
70#endif
71 }
72
73public:
74 typename std::add_lvalue_reference<_Tp>::type operator[](size_t __i) const {
75 const auto ptr = original::get();
76 if (MemorySafety<SAFE>::enabled) {
77 AssertNotNull(null: !ptr);
78 }
79 return ptr[__i];
80 }
81};
82
83template <typename T>
84using unique_array = unique_ptr<T[], std::default_delete<T>, true>;
85
86template <typename T>
87using unsafe_unique_array = unique_ptr<T[], std::default_delete<T>, false>;
88
89template <typename T>
90using unsafe_unique_ptr = unique_ptr<T, std::default_delete<T>, false>;
91
92} // namespace duckdb
93