util/attempt.h: introduce 'Ok' type

This type alleviates the need to re-introduce custom '*_ok' types
whenever a result can be an error but no value.
This commit is contained in:
Norman Feske 2025-04-05 14:02:13 +02:00
parent 2e76f4fc58
commit fee2f354dc
28 changed files with 60 additions and 87 deletions

View File

@ -87,30 +87,11 @@ class Core::Platform : public Platform_generic
*/
struct Pseudo_ram_allocator : Range_allocator
{
Alloc_result try_alloc(size_t) override
{
return nullptr;
}
Alloc_result alloc_aligned(size_t, unsigned, Range) override
{
return nullptr;
}
Alloc_result alloc_addr(size_t, addr_t) override
{
return nullptr;
}
Range_result add_range(addr_t, size_t) override
{
return Range_ok();
}
Range_result remove_range(addr_t, size_t) override
{
return Range_ok();
}
Alloc_result try_alloc(size_t) override { return nullptr; }
Alloc_result alloc_aligned(size_t, unsigned, Range) override { return nullptr; }
Alloc_result alloc_addr(size_t, addr_t) override { return nullptr; }
Range_result add_range(addr_t, size_t) override { return Ok(); }
Range_result remove_range(addr_t, size_t) override { return Ok(); }
void free(void *) override { }
void free(void *, size_t) override { }

View File

@ -137,8 +137,7 @@ struct Genode::Range_allocator : Allocator
/**
* Return type of range-management operations
*/
struct Range_ok { };
using Range_result = Attempt<Range_ok, Alloc_error>;
using Range_result = Attempt<Ok, Alloc_error>;
/**
* Add free address range to allocator

View File

@ -63,8 +63,7 @@ class Genode::Slab : public Allocator
*/
void _insert_sb(Block *);
struct Expand_ok { };
using Expand_result = Attempt<Expand_ok, Alloc_error>;
using Expand_result = Attempt<Ok, Alloc_error>;
/**
* Expand slab by one block

View File

@ -26,9 +26,8 @@ namespace Genode { namespace Trace {
using Thread_name = String<32>;
struct Num_subjects { unsigned value; };
struct Policy_size { size_t num_bytes; };
struct Buffer_size { size_t num_bytes; };
struct Trace_ok { };
struct Policy_size { size_t num_bytes; };
struct Buffer_size { size_t num_bytes; };
struct Policy_id;
struct Subject_id;

View File

@ -353,9 +353,8 @@ struct Genode::Pd_session : Session, Pd_account
virtual addr_t dma_addr(Ram_dataspace_capability) = 0;
enum class Attach_dma_error { OUT_OF_RAM, OUT_OF_CAPS, DENIED };
struct Attach_dma_ok { };
using Attach_dma_result = Attempt<Attach_dma_ok, Attach_dma_error>;
using Attach_dma_result = Attempt<Ok, Attach_dma_error>;
/**
* Attach dataspace to I/O page table at specified address 'at'

View File

@ -96,7 +96,7 @@ struct Genode::Trace::Connection : Genode::Connection<Genode::Trace::Session>,
void unload_policy(Policy_id id) { call<Rpc_unload_policy>(id); }
enum class Trace_error { FOREIGN, SOURCE_IS_DEAD, INVALID_SUBJECT, INVALID_POLICY };
using Trace_result = Attempt<Trace_ok, Trace_error>;
using Trace_result = Attempt<Ok, Trace_error>;
/**
* Start tracing of a subject
@ -108,7 +108,7 @@ struct Genode::Trace::Connection : Genode::Connection<Genode::Trace::Session>,
return call<Rpc_trace>(s, p, size); });
return rpc_result.convert<Trace_result>(
[&] (Trace_ok ok) { return ok; },
[&] (Ok ok) { return ok; },
[&] (Trace_rpc_error e) {
switch (e) {
case Trace_rpc_error::OUT_OF_RAM: /* cannot occur, handled by '_retry' above */

View File

@ -40,7 +40,7 @@ struct Genode::Trace::Session : Genode::Session
using Alloc_policy_rpc_result = Attempt<Policy_id, Alloc_policy_rpc_error>;
using Subjects_rpc_result = Attempt<Num_subjects, Alloc_rpc_error>;
using Infos_rpc_result = Attempt<Num_subjects, Alloc_rpc_error>;
using Trace_rpc_result = Attempt<Trace_ok, Trace_rpc_error>;
using Trace_rpc_result = Attempt<Ok, Trace_rpc_error>;
virtual ~Session() { }

View File

@ -19,6 +19,11 @@
namespace Genode {
template <typename, typename> struct Attempt;
template <typename, typename> struct Unique_attempt;
/**
* Type used for results with no return value but error conditions
*/
struct Ok { };
}

View File

@ -102,8 +102,7 @@ class Core::Trace::Policy_registry
_policies.remove(p);
}
struct Insert_ok { };
using Insert_result = Attempt<Insert_ok, Ram::Error>;
using Insert_result = Attempt<Ok, Ram::Error>;
Insert_result insert(Policy_owner const &owner, Policy_id const id,
Allocator &md_alloc, Ram::Allocator &ram,
@ -115,7 +114,7 @@ class Core::Trace::Policy_registry
Policy &policy = *new (&md_alloc) Policy(owner, id, md_alloc, ram, size);
_policies.insert(&policy);
return policy.ds.convert<Insert_result>(
[&] (Ram::Allocation const &) { return Insert_ok(); },
[&] (Ram::Allocation const &) { return Ok(); },
[&] (Ram::Error e) { return e; });
}
catch (Out_of_ram) { return Ram::Error::OUT_OF_RAM; }

View File

@ -366,7 +366,7 @@ Region_map_component::attach_dma(Dataspace_capability ds_cap, addr_t at)
using Attach_dma_error = Pd_session::Attach_dma_error;
return _attach(ds_cap, attr).convert<Attach_dma_result>(
[&] (Range) { return Pd_session::Attach_dma_ok(); },
[&] (Range) { return Ok(); },
[&] (Attach_error e) {
switch (e) {
case Attach_error::OUT_OF_RAM: return Attach_dma_error::OUT_OF_RAM;

View File

@ -120,7 +120,7 @@ Session_component::trace(Subject_id subject_id, Policy_id policy_id, Buffer_size
{
using Result = Subject::Trace_result;
switch (result) {
case Result::OK: return Trace_ok { };
case Result::OK: return Ok { };
case Result::OUT_OF_RAM: return Trace_rpc_error::OUT_OF_RAM;
case Result::OUT_OF_CAPS: return Trace_rpc_error::OUT_OF_CAPS;
case Result::FOREIGN: return Trace_rpc_error::FOREIGN;

View File

@ -254,7 +254,7 @@ Allocator_avl_base::Range_result Allocator_avl_base::add_range(addr_t new_addr,
/* create new block that spans over all merged blocks */
_add_block(*new_block_ptr, new_addr, new_size, Block::FREE);
return Range_ok();
return Ok();
},
[&] (Alloc_error error) {
return error; });
@ -287,7 +287,7 @@ Allocator_avl_base::Range_result Allocator_avl_base::remove_range(addr_t base, s
_md_alloc.free(blocks.b2_ptr, sizeof(Block));
if (b == 0)
result = Range_ok();
result = Ok();
done = true;
return;

View File

@ -138,7 +138,7 @@ Heap::_allocate_dataspace(size_t size, bool enforce_separate_metadata)
/* add new local address range to our local allocator */
_alloc->add_range(attach_guard.range.start, size).with_result(
[&] (Range_allocator::Range_ok) {
[&] (Ok) {
metadata = _alloc->alloc_aligned(sizeof(Heap::Dataspace), log2(16U)); },
[&] (Alloc_error error) {
metadata = error; });

View File

@ -331,7 +331,7 @@ void Slab::_insert_sb(Block *sb)
Slab::Expand_result Slab::_expand()
{
if (!_backing_store || _nested)
return Expand_ok();
return Ok();
/* allocate new block for slab */
_nested = true;
@ -353,7 +353,7 @@ Slab::Expand_result Slab::_expand()
* list.
*/
_insert_sb(sb_ptr);
return Expand_ok(); },
return Ok(); },
[&] (Alloc_error error) {
return error; });
@ -387,8 +387,8 @@ Allocator::Alloc_result Slab::try_alloc(size_t size)
Expand_result expand_result = _expand();
if (expand_result.failed())
return expand_result.convert<Alloc_result>(
[&] (Expand_ok) { return Alloc_error::DENIED; },
[&] (Alloc_error error) { return error; });
[&] (Ok) { return Alloc_error::DENIED; },
[&] (Alloc_error e) { return e; });
}
/* skip completely occupied slab blocks, detect cycles */

View File

@ -395,8 +395,7 @@ struct Slab_backend_alloc : public Genode::Allocator,
Genode::Allocator_avl _range;
Genode::Ram_allocator &_ram;
struct Extend_ok { };
using Extend_result = Genode::Attempt<Extend_ok, Alloc_error>;
using Extend_result = Genode::Attempt<Ok, Alloc_error>;
Extend_result _extend_one_block()
{
@ -430,8 +429,8 @@ struct Slab_backend_alloc : public Genode::Allocator,
return _range.add_range(_base + range.start, range.num_bytes)
.convert<Extend_result>(
[&] (Range_allocator::Range_ok) { return Extend_ok(); },
[&] (Alloc_error e) { return e; });
[&] (Ok) { return Ok(); },
[&] (Alloc_error e) { return e; });
},
[&] (Region_map::Attach_error e) {
@ -479,8 +478,8 @@ struct Slab_backend_alloc : public Genode::Allocator,
return result;
return _extend_one_block().convert<Alloc_result>(
[&] (Extend_ok) { return _range.try_alloc(size); },
[&] (Alloc_error error) { return error; });
[&] (Ok) { return _range.try_alloc(size); },
[&] (Alloc_error e) { return e; });
}
void free(void *addr, Genode::size_t size) { _range.free(addr, size); }

View File

@ -112,9 +112,9 @@ class Timed_semaphore
{
public:
struct Down_ok { };
struct Down_timed_out { };
using Down_result = Genode::Attempt<Down_ok, Down_timed_out>;
using Ok = Genode::Ok;
using Down_result = Genode::Attempt<Ok, Down_timed_out>;
private:
@ -198,7 +198,7 @@ class Timed_semaphore
blockade.block();
if (wakeup_called)
return Down_ok();
return Ok();
else
return Down_timed_out();
}
@ -338,7 +338,7 @@ class Timed_semaphore
} else {
_meta_mutex.release();
return Down_ok();
return Ok();
}
}
};

View File

@ -243,7 +243,7 @@ struct Cond
Genode::Microseconds(timeout_ms(currtime, *abstime) * 1000);
signal_sem.down(true, timeout_us).with_result(
[&] (Timed_semaphore::Down_ok) { },
[&] (Timed_semaphore::Ok) { },
[&] (Timed_semaphore::Down_timed_out) { result = -2; }
);
}

View File

@ -32,8 +32,7 @@ class Pcapng::Write_buffer
public:
enum class Append_error { OUT_OF_MEM, OVERFLOW };
struct Append_ok { };
using Append_result = Attempt<Append_ok, Append_error>;
using Append_result = Attempt<Ok, Append_error>;
private:
@ -59,7 +58,7 @@ class Pcapng::Write_buffer
_total_length += block.size();
return Append_ok();
return Ok();
}
void write_to_file(Genode::Append_file &dst, Directory::Path const &path)

View File

@ -113,10 +113,9 @@ struct Extract::Extracted_archive : Noncopyable
struct Strip { unsigned value; };
struct Extract_ok { };
enum class Extract_error : uint32_t {
OPEN_FAILED, READ_FAILED, WRITE_FAILED, };
using Extract_result = Attempt<Extract_ok, Extract_error>;
using Extract_result = Attempt<Ok, Extract_error>;
/**
* \param path path to archive file
@ -223,7 +222,7 @@ struct Extract::Extracted_archive : Noncopyable
return Extract_error::WRITE_FAILED;
}
return Extract_ok();
return Ok();
}
};
@ -279,7 +278,7 @@ struct Extract::Main
Extracted_archive archive;
archive.extract(src_path, strip, raw_name).with_result(
[&] (Extracted_archive::Extract_ok) {
[&] (Ok) {
if (_verbose)
log("extracted '", src_path, "' to '", dst_path, "'");

View File

@ -193,7 +193,7 @@ Symlink_resolve_result Libc::resolve_symlinks(char const *path, Absolute_path &r
resolved_path = next_iteration_working_path;
resolved_path.remove_trailing('/');
return Symlinks_resolved_ok();
return Ok();
}
@ -214,7 +214,7 @@ static Symlink_resolve_result resolve_symlinks_except_last_element(char const *p
return Symlink_resolve_error();
}
return Symlinks_resolved_ok();
return Ok();
}

View File

@ -28,9 +28,8 @@ namespace Libc {
using Absolute_path = Genode::Path<PATH_MAX>;
struct Symlinks_resolved_ok { };
struct Symlink_resolve_error { };
using Symlink_resolve_result = Attempt<Symlinks_resolved_ok, Symlink_resolve_error>;
using Symlink_resolve_result = Attempt<Ok, Symlink_resolve_error>;
Symlink_resolve_result resolve_symlinks(char const *path,
Absolute_path &resolved_path);

View File

@ -158,15 +158,13 @@ void Libc::Kernel::_init_file_descriptors()
resolved_path = next_iteration_working_path;
resolved_path.remove_trailing('/');
return Symlinks_resolved_ok();
return Ok();
};
using Path = String<Vfs::MAX_PATH_LEN>;
struct Absolute_path_resolved_ok { };
struct Absolute_path_resolve_error { };
using Absolute_path_resolve_result = Attempt<Absolute_path_resolved_ok,
Absolute_path_resolve_error>;
using Absolute_path_resolve_result = Attempt<Ok, Absolute_path_resolve_error>;
auto resolve_absolute_path = [&] (Path const &path, Absolute_path &abs_path) -> Absolute_path_resolve_result
{
@ -177,7 +175,7 @@ void Libc::Kernel::_init_file_descriptors()
if (resolve_symlinks(abs_dir, abs_path).failed())
return Absolute_path_resolve_error();
abs_path.append_element(dir_entry.string());
return Absolute_path_resolved_ok();
return Ok();
} catch (Path_base::Path_too_long) { return Absolute_path_resolve_error(); }
};

View File

@ -101,7 +101,7 @@ class Genode::Packet_allocator : public Genode::Range_allocator
if (bits_cnt > max_cnt)
_array->set(max_cnt, bits_cnt - max_cnt);
return Range_ok();
return Ok();
}
catch (Out_of_ram) { error = Alloc_error::OUT_OF_RAM; }
@ -134,7 +134,7 @@ class Genode::Packet_allocator : public Genode::Range_allocator
_bits = nullptr;
}
return Range_ok();
return Ok();
}
Alloc_result alloc_aligned(size_t size, unsigned, Range) override

View File

@ -67,7 +67,7 @@ void Device_pd::add_range(Io_mmu::Range const & range,
do {
_pd.attach_dma(cap, range.start).with_result(
[&] (Pd_session::Attach_dma_ok) {
[&] (Ok) {
/* trigger eager mapping of memory */
_pd.map(Pd_session::Virt_range { range.start, range.size });
retry = false;

View File

@ -22,9 +22,8 @@ using namespace Genode;
struct Entropy_source : Interface
{
struct Collect_ok { };
struct Collect_error { };
using Collect_result = Attempt<Collect_ok, Collect_error>;
using Collect_result = Attempt<Ok, Collect_error>;
virtual Collect_result collect(Byte_range_ptr const &dst) = 0;
};
@ -87,7 +86,7 @@ struct Xoroshiro_128_plus_reseeding
{
return _entropy_src.collect(Byte_range_ptr { (char*)&_seed,
sizeof(_seed) }).convert<bool>(
[&] (Entropy_source::Collect_ok) {
[&] (Ok) {
_consumed_limit = CONSUME_THRESHOLD + (_seed & 0xfffu);
_xoroshiro.construct(_seed);
return true;
@ -161,7 +160,7 @@ struct Vfs::Xoroshiro_file_system : Single_file_system
Collect_result collect(Byte_range_ptr const &dst) override
{
if (_seed_file.read(Readonly_file::At { 0 }, dst) >= dst.num_bytes)
return Collect_ok();
return Ok();
return Collect_error();
}

View File

@ -103,7 +103,7 @@ size_t Terminal_crosslink::Session_component::_write(size_t num_bytes)
while ((num_bytes_written < num_bytes) && !error)
_buffer.add(src[num_bytes_written]).with_result(
[&] (Ring_buffer::Add_ok) { ++num_bytes_written; },
[&] (Ok) { ++num_bytes_written; },
[&] (Ring_buffer::Add_error) { error = true; }
);

View File

@ -51,10 +51,9 @@ namespace Terminal_crosslink {
Ring_buffer(Byte_range_ptr const &buffer)
: _queue(buffer.start), _queue_size(buffer.num_bytes) { }
struct Add_ok { };
enum class Add_error { OVERFLOW };
using Add_result = Attempt<Add_ok, Add_error>;
using Add_result = Attempt<Ok, Add_error>;
/**
* Place element into ring buffer
@ -64,7 +63,7 @@ namespace Terminal_crosslink {
if ((_head + 1)%_queue_size != _tail) {
_queue[_head] = ev;
_head = (_head + 1)%_queue_size;
return Add_ok();
return Ok();
} else
return Add_error::OVERFLOW;
}

View File

@ -300,7 +300,7 @@ struct Test_tracing
_trace.trace(id, policy_id, Trace::Buffer_size{16384});
trace_result.with_result(
[&] (Trace::Trace_ok) {
[&] (Ok) {
Dataspace_capability ds_cap = _trace.buffer(id);
_test_monitor.construct(env.rm(), id, ds_cap);
},