blob: 65e2dee484aa8c433199a4955f0342c7d94c3055 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
#pragma once
#include "Base.h"
#include "cru/base/Base.h"
#include <cstdlib>
#include <functional>
#include <optional>
namespace cru {
struct Guard {
using ExitFunc = std::function<void()>;
Guard() = default;
explicit Guard(const ExitFunc& f) : on_exit(f) {}
explicit Guard(ExitFunc&& f) : on_exit(std::move(f)) {}
Guard(const Guard&) = delete;
Guard(Guard&&) = default;
Guard& operator=(const Guard&) = delete;
Guard& operator=(Guard&&) = default;
~Guard() {
if (on_exit) {
on_exit();
}
}
void Drop() { on_exit = {}; }
ExitFunc on_exit;
};
/**
* FreeFunc must handle nullptr correctly.
*/
template <typename T, void (*FreeFunc)(T*) noexcept>
struct TAutoFreePtr {
TAutoFreePtr(T* ptr) : ptr(ptr) {}
~TAutoFreePtr() { FreeFunc(ptr); }
CRU_DELETE_COPY(TAutoFreePtr)
TAutoFreePtr(TAutoFreePtr&& other) noexcept : ptr(other.ptr) {
other.ptr = nullptr;
}
TAutoFreePtr& operator=(TAutoFreePtr&& other) noexcept {
if (this != &other) {
FreeFunc(ptr);
ptr = other.ptr;
other.ptr = nullptr;
}
return *this;
}
operator T*() const { return ptr; }
T* operator->() { return ptr; }
T* ptr;
};
namespace details {
template <typename T>
inline void MyFree(T* p) noexcept {
::free(p);
}
} // namespace details
template <typename T>
using AutoFreePtr = TAutoFreePtr<T, details::MyFree<T>>;
template <typename T, void (*DestructFunc)(T value) noexcept>
class AutoDestruct {
public:
AutoDestruct() : value_(std::nullopt), auto_destruct_(false) {}
AutoDestruct(T value, bool auto_destruct = true)
: value_(std::move(value)), auto_destruct_(auto_destruct) {}
CRU_DELETE_COPY(AutoDestruct)
AutoDestruct(AutoDestruct&& other) noexcept
: value_(std::move(other.value_)), auto_destruct_(other.auto_destruct_) {
other.value_ = std::nullopt;
other.auto_destruct_ = false;
}
AutoDestruct& operator=(AutoDestruct&& other) noexcept {
if (this != &other) {
DoDestruct();
value_ = other.value_;
auto_destruct_ = other.auto_destruct_;
other.value_ = std::nullopt;
other.auto_destruct_ = false;
}
return *this;
}
~AutoDestruct() { DoDestruct(); }
public:
bool IsValid() const { return value_.has_value(); }
void CheckValid(
std::optional<std::string_view> additional_message = std::nullopt) const {
if (!IsValid()) {
std::string message("AutoDestruct contains no object.");
if (additional_message) {
message += " ";
message += *additional_message;
}
throw Exception(std::move(message));
}
}
const T& Get() const {
CheckValid();
return *value_;
}
T Release() {
CheckValid();
auto value = std::move(*value_);
value_ = std::nullopt;
auto_destruct_ = false;
return value;
}
void Reset(std::optional<T> value = std::nullopt) {
DoDestruct();
value_ = std::move(value);
}
explicit operator bool() const { return value_.has_value(); }
private:
void DoDestruct() {
if (auto_destruct_ && value_) {
DestructFunc(*value_);
}
}
private:
std::optional<T> value_;
bool auto_destruct_;
};
} // namespace cru
|