util/attempt.h: add 'Unique_attempt' utility

The new variant combines the attempt with unique-pointer semantics
and is thereby usable for returning non-copyable objects such as
RAM 'Allocation'.

Issue #5502
This commit is contained in:
Norman Feske 2025-04-04 12:45:12 +02:00
parent 7d4b6b6bd5
commit 2dfaeab7c2

View File

@ -14,7 +14,12 @@
#ifndef _INCLUDE__UTIL__ATTEMPT_H_
#define _INCLUDE__UTIL__ATTEMPT_H_
namespace Genode { template <typename, typename> struct Attempt; }
#include <util/reconstructible.h>
namespace Genode {
template <typename, typename> struct Attempt;
template <typename, typename> struct Unique_attempt;
}
/**
@ -80,4 +85,67 @@ class Genode::Attempt
bool failed() const { return !_ok; }
};
/**
* Base type for the result of constrained RAM allocations
*
* The type is a unique pointer to the allocated RAM while also holding
* allocation-error information, following the conventions of 'Attempt'.
*/
template <typename RESULT, typename ERROR>
class Genode::Unique_attempt : Noncopyable
{
private:
Constructible<RESULT> _result { };
ERROR _error { };
protected:
void _construct(auto &&... args) { _result.construct(args...); }
void _destruct (ERROR e) { _result.destruct(); _error = e; }
public:
Unique_attempt(auto &&... args) { _result.construct(args...); }
Unique_attempt(ERROR error) { _destruct(error); }
template <typename RET>
RET convert(auto const &access_fn, auto const &fail_fn)
{
return _result.constructed() ? RET { access_fn(*_result) }
: RET { fail_fn(_error) };
}
template <typename RET>
RET convert(auto const &access_fn, auto const &fail_fn) const
{
return _result.constructed() ? RET { access_fn(*_result) }
: RET { fail_fn(_error) };
}
void with_result(auto const &access_fn, auto const &fail_fn)
{
_result.constructed() ? access_fn(*_result) : fail_fn(_error);
}
void with_result(auto const &access_fn, auto const &fail_fn) const
{
_result.constructed() ? access_fn(*_result) : fail_fn(_error);
}
void with_error(auto const &fail_fn) const
{
if (!_result.constructed())
fail_fn(_error);
}
bool operator == (ERROR const &rhs) const {
return failed() && (_error == rhs); }
bool ok() const { return _result.constructed(); }
bool failed() const { return !_result.constructed(); }
};
#endif /* _INCLUDE__UTIL__ATTEMPT_H_ */