uvco 0.1
Loading...
Searching...
No Matches
internal_utils.h
Go to the documentation of this file.
1// uvco (c) 2023 Lewin Bormann. See LICENSE for specific terms.
2
3#pragma once
4
5#include <boost/assert.hpp>
6#include <fmt/core.h>
7#include <string_view>
8#include <uv.h>
9#include <uv/unix.h>
10
11#include <concepts>
12#include <cstddef>
13#include <string>
14#include <utility>
15
16namespace uvco {
17
20
22using uv_status = int;
23
24void allocator(uv_handle_t * /*unused*/, size_t sugg, uv_buf_t *buf);
25
26void freeUvBuf(const uv_buf_t *buf);
27
28// Checks if string_view is null-terminated. If it is, the fast path is taken.
29// Otherwise, a string is allocated which is null-terminated, and the function
30// is called with it.
31template <typename R, typename F>
32 requires std::is_invocable_r_v<R, F, std::string_view>
33R callWithNullTerminated(std::string_view view, F &&f) {
34 if (view.data()[view.size()] == '\0') {
35 return f(view.data());
36 }
37 std::string str(view);
38 return f(str.c_str());
39}
40
41template <typename Into, typename Handle> Into *getData(const Handle *handle) {
42 const void *data = uv_handle_get_data((const uv_handle_t *)handle);
43 BOOST_ASSERT(nullptr != data);
44 return (Into *)data;
45}
46
47template <typename Into, typename Request>
48Into *getRequestData(const Request *req) {
49 const void *data = uv_req_get_data((const uv_req_t *)req);
50 BOOST_ASSERT(nullptr != data);
51 return (Into *)data;
52}
53
54template <typename Handle, typename Data>
55void setData(Handle *handle, Data *data) {
56 BOOST_ASSERT(handle != nullptr);
57 uv_handle_set_data((uv_handle_t *)handle, (void *)data);
58}
59
60template <typename Request, typename Data>
61void setRequestData(Request *req, Data *data) {
62 BOOST_ASSERT(req != nullptr);
63 uv_req_set_data((uv_req_t *)req, (void *)data);
64}
65
66template <typename Handle> bool dataIsNull(Handle *handle) {
67 return nullptr == uv_handle_get_data((const uv_handle_t *)handle);
68}
69
70template <typename Request> bool requestDataIsNull(Request *req) {
71 return nullptr == uv_req_get_data((const uv_req_t *)req);
72}
73
79 static void del(uv_handle_t *handle);
80 template <typename Handle> void operator()(Handle *handle) {
81 del((uv_handle_t *)handle);
82 }
83};
84
98template <typename T> class RefCounted {
99public:
100 // Assignment doesn't change count.
101 RefCounted(const RefCounted &other) = default;
102 RefCounted &operator=(const RefCounted &other) = default;
103 RefCounted(RefCounted &&other) noexcept {}
104 RefCounted &operator=(RefCounted &&other) noexcept {}
105 virtual ~RefCounted() = default;
106
109 virtual T *addRef() {
110 ++count_;
111 return static_cast<T *>(this);
112 }
113
117 virtual void delRef() {
118 --count_;
119 if (count_ == 0) {
120 delete static_cast<T *>(this);
121 }
122 }
123
124protected:
125 RefCounted() = default;
126
127private:
128 size_t count_ = 1;
129};
130
132template <typename T, typename... Args>
133T *makeRefCounted(Args... args)
134 requires std::derived_from<T, RefCounted<T>>
135{
136 if constexpr (sizeof...(args) == 0) {
137 return new T{};
138 } else {
139 return new T{std::forward<Args...>(args...)};
140 }
141}
142
143extern const bool TRACK_LIFETIMES;
144
147template <typename T> class LifetimeTracker {
148public:
149 explicit LifetimeTracker(std::string name = "") : id_{std::move(name)} {
150 if (TRACK_LIFETIMES) {
151 fmt::print("ctor {}()#{}\n", typeid(T).name(), id_);
152 }
153 }
155 if (TRACK_LIFETIMES) {
156 fmt::print("ctor {}()#{}\n", typeid(T).name(), id_);
157 }
158 }
159 LifetimeTracker &operator=(LifetimeTracker && /*unused*/) noexcept {
160 if (TRACK_LIFETIMES) {
161 fmt::print("operator={}()#{}\n", typeid(T).name(), id_);
162 }
163 }
165 if (this == &other) {
166 return *this;
167 }
168 if (TRACK_LIFETIMES) {
169 fmt::print("operator={}({})#{}\n", typeid(T).name(), other.id_, id_);
170 }
171 id_ = fmt::format("{}/copy", other.id_);
172 }
174 : id_{fmt::format("{}/copy", other.id_)} {
175 if (TRACK_LIFETIMES) {
176 fmt::print("operator={}({})#{}\n", typeid(T).name(), other.id_, id_);
177 }
178 }
180 if (TRACK_LIFETIMES) {
181 fmt::print("dtor ~{}()\n", typeid(T).name());
182 }
183 }
184
185protected:
186 std::string id_;
187};
188
192public:
193 FlagGuard(const FlagGuard &) = delete;
194 FlagGuard(FlagGuard &&) = delete;
195 FlagGuard &operator=(const FlagGuard &) = delete;
197
199 explicit FlagGuard(bool &flag);
200 ~FlagGuard();
201
202private:
203 bool &flag_;
204};
205
206template <typename T> class ZeroAtExit {
207public:
208 explicit ZeroAtExit(T **pointer) : ptr_{pointer} {}
209 ZeroAtExit(const ZeroAtExit &) = delete;
210 ZeroAtExit(ZeroAtExit &&) = delete;
211 ZeroAtExit &operator=(const ZeroAtExit &) = delete;
214 if (ptr_ != nullptr) {
215 *ptr_ = nullptr;
216 }
217 }
218
219private:
220 T **ptr_ = nullptr;
221};
222
224
225} // namespace uvco
Definition internal_utils.h:191
~FlagGuard()
Definition internal_utils.cc:53
FlagGuard(FlagGuard &&)=delete
FlagGuard & operator=(FlagGuard &&)=delete
FlagGuard & operator=(const FlagGuard &)=delete
FlagGuard(const FlagGuard &)=delete
bool & flag_
Definition internal_utils.h:203
Definition internal_utils.h:147
LifetimeTracker(LifetimeTracker &&) noexcept
Definition internal_utils.h:154
LifetimeTracker(const LifetimeTracker< T > &other)
Definition internal_utils.h:173
LifetimeTracker< T > & operator=(const LifetimeTracker< T > &other)
Definition internal_utils.h:164
LifetimeTracker & operator=(LifetimeTracker &&) noexcept
Definition internal_utils.h:159
std::string id_
Definition internal_utils.h:186
~LifetimeTracker()
Definition internal_utils.h:179
LifetimeTracker(std::string name="")
Definition internal_utils.h:149
Definition internal_utils.h:98
RefCounted(RefCounted &&other) noexcept
Definition internal_utils.h:103
virtual T * addRef()
Definition internal_utils.h:109
RefCounted()=default
virtual ~RefCounted()=default
RefCounted(const RefCounted &other)=default
RefCounted & operator=(RefCounted &&other) noexcept
Definition internal_utils.h:104
RefCounted & operator=(const RefCounted &other)=default
virtual void delRef()
Definition internal_utils.h:117
size_t count_
Definition internal_utils.h:128
Definition internal_utils.h:206
~ZeroAtExit()
Definition internal_utils.h:213
ZeroAtExit & operator=(ZeroAtExit &&)=delete
ZeroAtExit(const ZeroAtExit &)=delete
ZeroAtExit(T **pointer)
Definition internal_utils.h:208
ZeroAtExit & operator=(const ZeroAtExit &)=delete
T ** ptr_
Definition internal_utils.h:220
ZeroAtExit(ZeroAtExit &&)=delete
const bool TRACK_LIFETIMES
Definition internal_utils.cc:15
void setData(Handle *handle, Data *data)
Definition internal_utils.h:55
bool requestDataIsNull(Request *req)
Definition internal_utils.h:70
Into * getRequestData(const Request *req)
Definition internal_utils.h:48
Into * getData(const Handle *handle)
Definition internal_utils.h:41
void freeUvBuf(const uv_buf_t *buf)
Definition internal_utils.cc:26
void setRequestData(Request *req, Data *data)
Definition internal_utils.h:61
int uv_status
Result of a libuv operation, an errno error code.
Definition internal_utils.h:22
void allocator(uv_handle_t *, size_t sugg, uv_buf_t *buf)
libuv allocator.
Definition internal_utils.cc:18
bool dataIsNull(Handle *handle)
Definition internal_utils.h:66
R callWithNullTerminated(std::string_view view, F &&f)
Definition internal_utils.h:33
T * makeRefCounted(Args... args)
Create a new refcounted value. T must derive from RefCounted<T>.
Definition internal_utils.h:133
Definition async_work.cc:17
Definition internal_utils.h:78
void operator()(Handle *handle)
Definition internal_utils.h:80
static void del(uv_handle_t *handle)
Definition internal_utils.cc:31