oom safety implementations

This commit is contained in:
keldu 2021-03-17 11:24:18 +01:00
parent e45872d0c0
commit 86cb9e3d6e
6 changed files with 33 additions and 55 deletions

View File

@ -313,9 +313,9 @@ ErrorOr<AsyncIoContext> setupAsyncIo() {
EventLoop &loop_ref = io_provider->eventLoop(); EventLoop &loop_ref = io_provider->eventLoop();
return {std::move(io_provider), loop_ref, prt_ref}; return {{std::move(io_provider), loop_ref, prt_ref}};
} catch (std::bad_alloc &) { } catch (std::bad_alloc &) {
return criticalError(""); return criticalError("Out of memory");
} }
} }
} // namespace gin } // namespace gin

View File

@ -276,13 +276,18 @@ void ConveyorSinks::fail(Error &&error) {
void ConveyorSinks::add(Conveyor<void> &&sink) { void ConveyorSinks::add(Conveyor<void> &&sink) {
auto nas = Conveyor<void>::fromConveyor(std::move(sink)); auto nas = Conveyor<void>::fromConveyor(std::move(sink));
Own<SinkConveyorNode> sink_node =
heap<SinkConveyorNode>(std::move(nas.first), *this); Own<SinkConveyorNode> sink_node = nullptr;
try {
sink_node = heap<SinkConveyorNode>(std::move(nas.first), *this);
}catch(std::bad_alloc&){
return;
}
if (nas.second) { if (nas.second) {
nas.second->setParent(sink_node.get()); nas.second->setParent(sink_node.get());
} }
sink_nodes.push_back(std::move(sink_node)); sink_nodes.emplace_back(std::move(sink_node));
} }
void ConveyorSinks::fire() { void ConveyorSinks::fire() {

View File

@ -668,4 +668,4 @@ public:
} // namespace gin } // namespace gin
#include "async.tmpl.h" #include "async.tmpl.h"

View File

@ -15,53 +15,16 @@ namespace gin {
classname(const classname &) = delete; \ classname(const classname &) = delete; \
classname &operator=(const classname &) = delete classname &operator=(const classname &) = delete
template <typename T> using Maybe = std::optional<T>; template<typename T> using Maybe = std::optional<T>;
template <typename T> class Own { template <typename T> using Own = std::unique_ptr<T>;
private:
T *data = nullptr;
public:
Own() = default;
Own(T *d) : data{d} {}
~Own() {
if (data) {
delete data;
}
}
Own(Own<T> &&rhs) : data{rhs.data} { rhs.data = nullptr; }
Own<T> &operator=(Own<T> &&rhs) {
if (data) {
delete data;
}
data = rhs.data;
rhs.data = nullptr;
return *this;
}
T *operator->() const noexcept { return data; }
explicit operator bool() const noexcept { return data; }
T *get() noexcept { return data; }
typename std::add_lvalue_reference<T>::type operator*() const {
return *data;
}
GIN_FORBID_COPY(Own);
};
template <typename T> using Our = std::shared_ptr<T>; template <typename T> using Our = std::shared_ptr<T>;
template <typename T> using Lent = std::weak_ptr<T>; template <typename T> using Lent = std::weak_ptr<T>;
template <typename T, class... Args> Own<T> heap(Args &&...args) { template <typename T, class... Args> Own<T> heap(Args &&...args) {
return Own<T>(new T{std::forward<Args>(args)...}); return Own<T>(new (std::nothrow) T(std::forward<Args>(args)...));
} }
template <typename T, class... Args> Our<T> share(Args &&...args) { template <typename T, class... Args> Our<T> share(Args &&...args) {
@ -90,4 +53,4 @@ template <typename T> using UnfixVoid = typename VoidUnfix<T>::Type;
template <typename Func, typename T> template <typename Func, typename T>
using ReturnType = typename ReturnTypeHelper<Func, T>::Type; using ReturnType = typename ReturnTypeHelper<Func, T>::Type;
} // namespace gin } // namespace gin

View File

@ -9,14 +9,24 @@ Error::Error(const std::string_view &msg, int8_t code)
Error::Error(std::string &&msg, int8_t code) Error::Error(std::string &&msg, int8_t code)
: error_message{std::move(msg)}, error_{code} {} : error_message{std::move(msg)}, error_{code} {}
Error::Error(const Error &error)
: error_message{error.error_message}, error_{error.error_} {}
Error::Error(Error &&error) Error::Error(Error &&error)
: error_message{std::move(error.error_message)}, error_{std::move( : error_message{std::move(error.error_message)}, error_{std::move(
error.error_)} {} error.error_)} {}
const std::string_view Error::message() const { return error_message; } const std::string_view Error::message() const {
return std::visit([this](auto&& arg) -> const std::string_view {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, std::string>){
return std::string_view{arg};
}else if constexpr (std::is_same_v<T, std::string_view>){
return arg;
}else{
return "Error. Good luck :)";
}
}, error_message);
}
bool Error::failed() const { return error_ != 0; } bool Error::failed() const { return error_ != 0; }

View File

@ -38,7 +38,7 @@ public:
template <typename Formatter> template <typename Formatter>
Error makeError(const Formatter &formatter, int8_t code, Error makeError(const Formatter &formatter, int8_t code,
const std::string_view &generic = "") { const std::string_view &generic) {
try { try {
std::string error_msg = formatter(); std::string error_msg = formatter();
return Error{std::move(error_msg), code}; return Error{std::move(error_msg), code};
@ -53,7 +53,7 @@ Error criticalError(const std::string_view &generic) {
template <typename Formatter> template <typename Formatter>
Error criticalError(const Formatter &formatter, Error criticalError(const Formatter &formatter,
const std::string_view &generic = "") { const std::string_view &generic) {
return makeError(formatter, -1, generic); return makeError(formatter, -1, generic);
} }
@ -63,7 +63,7 @@ Error recoverableError(const std::string_view &generic) {
template <typename Formatter> template <typename Formatter>
Error recoverableError(const Formatter &formatter, Error recoverableError(const Formatter &formatter,
const std::string_view &generic = "") { const std::string_view &generic) {
return makeError(formatter, -1, generic); return makeError(formatter, -1, generic);
} }
@ -116,4 +116,4 @@ public:
const T &value() const { return std::get<T>(value_or_error); } const T &value() const { return std::get<T>(value_or_error); }
}; };
} // namespace gin } // namespace gin