base/include: use C++20 function template syntax

Issue #5227
This commit is contained in:
Norman Feske
2024-05-22 16:35:38 +02:00
committed by Christian Helmuth
parent 48d6f0220c
commit 5e862b2cd3
38 changed files with 173 additions and 254 deletions

View File

@ -26,7 +26,7 @@ namespace Genode {
struct Allocator; struct Allocator;
struct Range_allocator; struct Range_allocator;
template <typename T, typename DEALLOC> void destroy(DEALLOC && dealloc, T *obj); template <typename T> void destroy(auto && dealloc, T *obj);
} }
@ -276,8 +276,8 @@ inline void operator delete (void *ptr, Genode::Allocator &a) {
* was allocated * was allocated
* \param obj object to destroy * \param obj object to destroy
*/ */
template <typename T, typename DEALLOC> template <typename T>
void Genode::destroy(DEALLOC && dealloc, T *obj) void Genode::destroy(auto && dealloc, T *obj)
{ {
if (!obj) if (!obj)
return; return;

View File

@ -207,11 +207,9 @@ class Genode::Allocator_avl_base : public Range_allocator
*/ */
void _cut_from_block(Block &b, addr_t cut_addr, size_t cut_size, Two_blocks); void _cut_from_block(Block &b, addr_t cut_addr, size_t cut_size, Two_blocks);
template <typename ANY_BLOCK_FN> bool _revert_block_ranges(auto const &any_block_fn);
bool _revert_block_ranges(ANY_BLOCK_FN const &);
template <typename SEARCH_FN> Alloc_result _allocate(size_t, unsigned, Range, auto const &search_fn);
Alloc_result _allocate(size_t, unsigned, Range, SEARCH_FN const &);
protected: protected:
@ -427,8 +425,7 @@ class Genode::Allocator_avl_tpl : public Allocator_avl_base
* the method repeatedly without removing or inserting * the method repeatedly without removing or inserting
* members will produce the same member. * members will produce the same member.
*/ */
template <typename FUNC> bool apply_any(auto const &fn)
bool apply_any(FUNC const &fn)
{ {
addr_t addr = 0; addr_t addr = 0;
if (any_block_addr(&addr)) { if (any_block_addr(&addr)) {

View File

@ -214,9 +214,10 @@ struct Genode::Child_policy
* the case for a debug monitor - the address space must be accessed by * the case for a debug monitor - the address space must be accessed by
* component-local method calls instead. * component-local method calls instead.
*/ */
template <typename FN> void with_address_space(Pd_session &pd, auto const &fn)
void with_address_space(Pd_session &pd, FN const &fn)
{ {
using FN = decltype(fn);
struct Impl : With_address_space_fn struct Impl : With_address_space_fn
{ {
FN const &_fn; FN const &_fn;
@ -323,8 +324,7 @@ class Genode::Child : protected Rpc_object<Parent>,
Child_policy &_policy; Child_policy &_policy;
/* print error message with the child's name prepended */ /* print error message with the child's name prepended */
template <typename... ARGS> void _error(auto &&... args) { error(_policy.name(), ": ", args...); }
void _error(ARGS &&... args) { error(_policy.name(), ": ", args...); }
Region_map &_local_rm; Region_map &_local_rm;
@ -786,8 +786,7 @@ class Genode::Child : protected Rpc_object<Parent>,
void close_all_sessions(); void close_all_sessions();
template <typename FN> void for_each_session(auto const &fn) const
void for_each_session(FN const &fn) const
{ {
_id_space.for_each<Session_state const>(fn); _id_space.for_each<Session_state const>(fn);
} }

View File

@ -71,14 +71,13 @@ class Genode::Connection_base : Noncopyable, Interface
* *
* \noapi * \noapi
*/ */
template <typename FUNC> auto retry_with_upgrade(Ram_quota ram, Cap_quota caps, auto const &fn) -> decltype(fn())
auto retry_with_upgrade(Ram_quota ram, Cap_quota caps, FUNC func) -> decltype(func())
{ {
enum { UPGRADE_ATTEMPTS = ~0U }; enum { UPGRADE_ATTEMPTS = ~0U };
return Genode::retry<Out_of_ram>( return Genode::retry<Out_of_ram>(
[&] () { [&] () {
return Genode::retry<Out_of_caps>( return Genode::retry<Out_of_caps>(
[&] () { return func(); }, [&] () { return fn(); },
[&] () { upgrade_caps(caps.value); }, [&] () { upgrade_caps(caps.value); },
UPGRADE_ATTEMPTS); UPGRADE_ATTEMPTS);
}, },

View File

@ -148,8 +148,7 @@ class Genode::Heap : public Allocator
/** /**
* Call 'fn' with the start and size of each backing-store region * Call 'fn' with the start and size of each backing-store region
*/ */
template <typename FN> void for_each_region(auto const &fn) const
void for_each_region(FN const &fn) const
{ {
Mutex::Guard guard(_mutex); Mutex::Guard guard(_mutex);
for (Dataspace const *ds = _ds_pool.first(); ds; ds = ds->next()) for (Dataspace const *ds = _ds_pool.first(); ds; ds = ds->next())

View File

@ -63,8 +63,8 @@ class Genode::Id_space : public Noncopyable
return e ? e->_lookup(id) : 0; return e ? e->_lookup(id) : 0;
} }
template <typename ARG, typename FUNC> template <typename ARG>
void _for_each(FUNC const &fn) const void _for_each(auto const &fn) const
{ {
if (Avl_node<Element>::child(Avl_node_base::LEFT)) if (Avl_node<Element>::child(Avl_node_base::LEFT))
Avl_node<Element>::child(Avl_node_base::LEFT)->template _for_each<ARG>(fn); Avl_node<Element>::child(Avl_node_base::LEFT)->template _for_each<ARG>(fn);
@ -173,8 +173,8 @@ class Genode::Id_space : public Noncopyable
* This function is called with the ID space locked. Hence, it is not * This function is called with the ID space locked. Hence, it is not
* possible to modify the ID space from within 'fn'. * possible to modify the ID space from within 'fn'.
*/ */
template <typename ARG, typename FUNC> template <typename ARG>
void for_each(FUNC const &fn) const void for_each(auto const &fn) const
{ {
Mutex::Guard guard(_mutex); Mutex::Guard guard(_mutex);
@ -189,9 +189,9 @@ class Genode::Id_space : public Noncopyable
* *
* \throw Unknown_id * \throw Unknown_id
*/ */
template <typename ARG, typename FUNC> template <typename ARG, typename FN>
auto apply(Id id, FUNC const &fn) auto apply(Id id, FN const &fn)
-> typename Trait::Functor<decltype(&FUNC::operator())>::Return_type -> typename Trait::Functor<decltype(&FN::operator())>::Return_type
{ {
T *obj = nullptr; T *obj = nullptr;
{ {
@ -222,8 +222,8 @@ class Genode::Id_space : public Noncopyable
* \return true if 'fn' was applied, or * \return true if 'fn' was applied, or
* false if the ID space is empty. * false if the ID space is empty.
*/ */
template <typename ARG, typename FUNC> template <typename ARG>
bool apply_any(FUNC const &fn) bool apply_any(auto const &fn)
{ {
T *obj = nullptr; T *obj = nullptr;
{ {

View File

@ -58,8 +58,7 @@ class Genode::Log
Log(Output &output) : _output(output) { } Log(Output &output) : _output(output) { }
template <typename... ARGS> void output(Type type, auto &&... args)
void output(Type type, ARGS &&... args)
{ {
/* /*
* This function is being inlined. Hence, we try to keep it as * This function is being inlined. Hence, we try to keep it as
@ -82,8 +81,7 @@ class Genode::Log
*/ */
struct Log_fn struct Log_fn
{ {
template <typename... ARGS> Log_fn(auto && ... args) { log().output(LOG, args...); }
Log_fn(ARGS && ... args) { log().output(LOG, args...); }
}; };
}; };
@ -103,8 +101,7 @@ class Genode::Raw
public: public:
template <typename... ARGS> static void output(auto &&... args)
static void output(ARGS &&... args)
{ {
_acquire(); _acquire();
Output::out_args(_output(), args...); Output::out_args(_output(), args...);
@ -132,8 +129,7 @@ class Genode::Trace_output
Trace_output() { } Trace_output() { }
template <typename... ARGS> void output(auto &&... args)
void output(ARGS &&... args)
{ {
Buffered_trace_output buffered_trace_output Buffered_trace_output buffered_trace_output
{ Write_trace_fn() }; { Write_trace_fn() };
@ -152,8 +148,7 @@ class Genode::Trace_output
*/ */
struct Fn struct Fn
{ {
template <typename... ARGS> Fn(auto && ... args)
Fn(ARGS && ... args)
{ {
trace_output().output(Trace::timestamp(), ": ", args...); trace_output().output(Trace::timestamp(), ": ", args...);
} }
@ -166,8 +161,7 @@ namespace Genode {
/** /**
* Write 'args' as a regular message to the log * Write 'args' as a regular message to the log
*/ */
template <typename... ARGS> void log(auto &&... args) { Log::Log_fn(args...); }
void log(ARGS &&... args) { Log::Log_fn(args...); }
/** /**
@ -177,8 +171,7 @@ namespace Genode {
* the description of the 'error' function regarding the convention of * the description of the 'error' function regarding the convention of
* formatting error/warning messages. * formatting error/warning messages.
*/ */
template <typename... ARGS> void warning(auto &&... args) { Log::log().output(Log::WARNING, args...); }
void warning(ARGS &&... args) { Log::log().output(Log::WARNING, args...); }
/** /**
@ -189,8 +182,7 @@ namespace Genode {
* message. By convention, the actual message should be brief, starting * message. By convention, the actual message should be brief, starting
* with a lower-case character. * with a lower-case character.
*/ */
template <typename... ARGS> void error(auto &&... args) { Log::log().output(Log::ERROR, args...); }
void error(ARGS &&... args) { Log::log().output(Log::ERROR, args...); }
/** /**
@ -198,8 +190,7 @@ namespace Genode {
* *
* This function is intended for temporarily debugging purposes only. * This function is intended for temporarily debugging purposes only.
*/ */
template <typename... ARGS> void raw(auto &&... args) { Raw::output(args...); }
void raw(ARGS &&... args) { Raw::output(args...); }
/** /**
@ -207,8 +198,7 @@ namespace Genode {
* *
* The message is prefixed with a timestamp value * The message is prefixed with a timestamp value
*/ */
template <typename... ARGS> void trace(auto && ... args) { Trace_output::Fn(args...); }
void trace(ARGS && ... args) { Trace_output::Fn(args...); }
} }

View File

@ -120,11 +120,11 @@ class Genode::Object_pool : Interface, Noncopyable
_tree.remove(obj); _tree.remove(obj);
} }
template <typename FUNC> template <typename FN>
auto apply(unsigned long capid, FUNC func) auto apply(unsigned long capid, FN const &fn)
-> typename Trait::Functor<decltype(&FUNC::operator())>::Return_type -> typename Trait::Functor<decltype(&FN::operator())>::Return_type
{ {
using Functor = Trait::Functor<decltype(&FUNC::operator())>; using Functor = Trait::Functor<decltype(&FN::operator())>;
using Object_pointer = typename Functor::template Argument<0>::Type; using Object_pointer = typename Functor::template Argument<0>::Type;
using Weak_ptr = Weak_ptr<typename Entry::Entry_lock>; using Weak_ptr = Weak_ptr<typename Entry::Entry_lock>;
using Locked_ptr = Locked_ptr<typename Entry::Entry_lock>; using Locked_ptr = Locked_ptr<typename Entry::Entry_lock>;
@ -144,19 +144,18 @@ class Genode::Object_pool : Interface, Noncopyable
Locked_ptr lock_ptr(ptr); Locked_ptr lock_ptr(ptr);
Object_pointer op = lock_ptr.valid() Object_pointer op = lock_ptr.valid()
? dynamic_cast<Object_pointer>(&lock_ptr->obj) : nullptr; ? dynamic_cast<Object_pointer>(&lock_ptr->obj) : nullptr;
return func(op); return fn(op);
} }
} }
template <typename FUNC> template <typename FN>
auto apply(Untyped_capability cap, FUNC func) auto apply(Untyped_capability cap, FN const &fn)
-> typename Trait::Functor<decltype(&FUNC::operator())>::Return_type -> typename Trait::Functor<decltype(&FN::operator())>::Return_type
{ {
return apply(cap.local_name(), func); return apply(cap.local_name(), fn);
} }
template <typename FUNC> void remove_all(auto const &fn)
void remove_all(FUNC func)
{ {
using Weak_ptr = Weak_ptr<typename Entry::Entry_lock>; using Weak_ptr = Weak_ptr<typename Entry::Entry_lock>;
using Locked_ptr = Locked_ptr<typename Entry::Entry_lock>; using Locked_ptr = Locked_ptr<typename Entry::Entry_lock>;
@ -178,7 +177,7 @@ class Genode::Object_pool : Interface, Noncopyable
} }
} }
func(obj); fn(obj);
} }
} }
}; };

View File

@ -43,15 +43,13 @@ struct Genode::Output : Interface
/** /**
* Helper for the sequential output of a variable list of arguments * Helper for the sequential output of a variable list of arguments
*/ */
template <typename HEAD, typename... TAIL> static void out_args(Output &output, auto && head, auto &&... tail)
static void out_args(Output &output, HEAD && head, TAIL &&... tail)
{ {
print(output, head); print(output, head);
out_args(output, tail...); out_args(output, tail...);
} }
template <typename LAST> static void out_args(Output &output, auto && last) { print(output, last); }
static void out_args(Output &output, LAST && last) { print(output, last); }
}; };
@ -82,8 +80,7 @@ namespace Genode {
* This function template takes precedence over the one that takes a * This function template takes precedence over the one that takes a
* constant object reference as argument. * constant object reference as argument.
*/ */
template <typename T> static inline void print(Output &output, auto *ptr)
static inline void print(Output &output, T *ptr)
{ {
print(output, (void const *)ptr); print(output, (void const *)ptr);
} }
@ -173,9 +170,8 @@ namespace Genode {
* output. If set to 'PAD', the leading zeros will be * output. If set to 'PAD', the leading zeros will be
* printed. * printed.
*/ */
template <typename T> explicit Hex(auto value, Prefix prefix = PREFIX, Pad pad = NO_PAD)
explicit Hex(T value, Prefix prefix = PREFIX, Pad pad = NO_PAD) : _value(value), _digits(2*sizeof(value)), _prefix(prefix), _pad(pad) { }
: _value(value), _digits(2*sizeof(T)), _prefix(prefix), _pad(pad) { }
void print(Output &output) const; void print(Output &output) const;
}; };
@ -224,8 +220,7 @@ namespace Genode {
* method is able to access object-internal state, which can thereby be * method is able to access object-internal state, which can thereby be
* incorporated into the textual output. * incorporated into the textual output.
*/ */
template <typename T> static inline void print(Output &output, auto const &obj)
static inline void print(Output &output, T const &obj)
{ {
obj.print(output); obj.print(output);
} }
@ -233,8 +228,7 @@ namespace Genode {
/** /**
* Print a variable number of arguments * Print a variable number of arguments
*/ */
template <typename HEAD, typename... TAIL> static inline void print(Output &output, auto const &head, auto &&... tail)
static inline void print(Output &output, HEAD const &head, TAIL &&... tail)
{ {
Output::out_args(output, head, tail...); Output::out_args(output, head, tail...);
} }

View File

@ -250,10 +250,10 @@ class Genode::Quota_guard
void acknowledge() { _ack = true; } void acknowledge() { _ack = true; }
}; };
template <typename RET, typename FN, typename ERROR_FN> template <typename RET>
RET with_reservation(UNIT const amount, RET with_reservation(UNIT const amount,
FN const &fn, auto const &fn,
ERROR_FN const &error_fn) auto const &error_fn)
{ {
if (!_guard.try_withdraw(amount.value)) if (!_guard.try_withdraw(amount.value))
return error_fn(); return error_fn();

View File

@ -109,13 +109,14 @@ struct Genode::Registry : private Registry_base
: Registry_base::Element(registry, &obj) { } : Registry_base::Element(registry, &obj) { }
}; };
template <typename FUNC> void for_each(auto const &fn)
void for_each(FUNC const &fn)
{ {
using FN = decltype(fn);
struct Typed_functor : Registry_base::Untyped_functor struct Typed_functor : Registry_base::Untyped_functor
{ {
FUNC const &_fn; FN const &_fn;
Typed_functor(FUNC const &fn) : _fn(fn) { } Typed_functor(FN const &fn) : _fn(fn) { }
void call(void *obj_ptr) override void call(void *obj_ptr) override
{ {
@ -127,8 +128,7 @@ struct Genode::Registry : private Registry_base
Registry_base::_for_each(untyped_functor); Registry_base::_for_each(untyped_functor);
} }
template <typename FUNC> void for_each(auto const &fn) const
void for_each(FUNC const &fn) const
{ {
Mutex::Guard guard(_mutex); Mutex::Guard guard(_mutex);
@ -170,8 +170,7 @@ class Genode::Registered : public T
*/ */
static_assert(__has_virtual_destructor(T), "registered object must have virtual destructor"); static_assert(__has_virtual_destructor(T), "registered object must have virtual destructor");
template <typename... ARGS> Registered(Registry<Registered<T> > &registry, auto &&... args)
Registered(Registry<Registered<T> > &registry, ARGS &&... args)
: T(args...), _element(registry, *this) { } : T(args...), _element(registry, *this) { }
}; };
@ -193,8 +192,7 @@ class Genode::Registered_no_delete : public T
public: public:
template <typename... ARGS> Registered_no_delete(Registry<Registered_no_delete<T> > &registry, auto &&... args)
Registered_no_delete(Registry<Registered_no_delete<T> > &registry, ARGS &&... args)
: T(args...), _element(registry, *this) { } : T(args...), _element(registry, *this) { }
}; };

View File

@ -77,8 +77,7 @@ class Genode::Service : public Ram_transfer::Account,
* session state. All subsequent 'Session_state' arguments correspond * session state. All subsequent 'Session_state' arguments correspond
* to the forwarded 'args'. * to the forwarded 'args'.
*/ */
template <typename... ARGS> Session_state &create_session(Factory &client_factory, auto &&... args)
Session_state &create_session(Factory &client_factory, ARGS &&... args)
{ {
return _factory(client_factory).create(*this, args...); return _factory(client_factory).create(*this, args...);
} }
@ -151,8 +150,7 @@ class Genode::Local_service : public Service
Factory &_factory; Factory &_factory;
template <typename FUNC> void _apply_to_rpc_obj(Session_state &session, auto const &fn)
void _apply_to_rpc_obj(Session_state &session, FUNC const &fn)
{ {
SESSION *rpc_obj = dynamic_cast<SESSION *>(session.local_ptr); SESSION *rpc_obj = dynamic_cast<SESSION *>(session.local_ptr);

View File

@ -101,8 +101,7 @@ class Genode::Session_object : private Ram_quota_guard,
* The method produces output only if the session is in diagnostic * The method produces output only if the session is in diagnostic
* mode (defined via the 'diag' session argument). * mode (defined via the 'diag' session argument).
*/ */
template <typename... ARGS> void diag(auto &&... args) const
void diag(ARGS &&... args) const
{ {
if (_diag.enabled) if (_diag.enabled)
log(RPC_INTERFACE::service_name(), " (", _label, ") ", args...); log(RPC_INTERFACE::service_name(), " (", _label, ") ", args...);
@ -111,8 +110,7 @@ class Genode::Session_object : private Ram_quota_guard,
/** /**
* Output label-prefixed error message * Output label-prefixed error message
*/ */
template <typename... ARGS> void error(auto &&... args) const
void error(ARGS &&... args) const
{ {
Genode::error(RPC_INTERFACE::service_name(), " (", _label, ") ", args...); Genode::error(RPC_INTERFACE::service_name(), " (", _label, ") ", args...);
} }
@ -120,8 +118,7 @@ class Genode::Session_object : private Ram_quota_guard,
/** /**
* Output label-prefixed error message * Output label-prefixed error message
*/ */
template <typename... ARGS> void warning(auto &&... args) const
void warning(ARGS &&... args) const
{ {
Genode::warning(RPC_INTERFACE::service_name(), " (", _label, ") ", args...); Genode::warning(RPC_INTERFACE::service_name(), " (", _label, ") ", args...);
} }

View File

@ -323,8 +323,7 @@ class Genode::Session_state::Factory : Noncopyable
* *
* \throw Allocator::Out_of_memory * \throw Allocator::Out_of_memory
*/ */
template <typename... ARGS> Session_state &create(auto &&... args)
Session_state &create(ARGS &&... args)
{ {
Session_state &session = *new (_slab) Session_state(args...); Session_state &session = *new (_slab) Session_state(args...);
session.owner(*this); session.owner(*this);

View File

@ -301,15 +301,16 @@ class Genode::Signal_receiver : Noncopyable
void remove(Signal_context const *re); void remove(Signal_context const *re);
template <typename FUNC> void for_each_locked(auto const &fn) const
void for_each_locked(FUNC && functor) const
{ {
Signal_context *context = _head; Signal_context *context = _head;
if (!context) return; if (!context)
return;
do { do {
Mutex::Guard mutex_guard(context->_mutex); Mutex::Guard mutex_guard(context->_mutex);
if (functor(*context)) return; if (fn(*context))
return;
context = context->_next; context = context->_next;
} while (context != _head); } while (context != _head);
} }

View File

@ -44,8 +44,7 @@ class Genode::Synced_allocator : public Allocator
using Guard = typename Synced_interface<ALLOC, Mutex>::Guard; using Guard = typename Synced_interface<ALLOC, Mutex>::Guard;
template <typename... ARGS> Synced_allocator(auto &&... args)
Synced_allocator(ARGS &&... args)
: _alloc(args...), _synced_object(_mutex, &_alloc) { } : _alloc(args...), _synced_object(_mutex, &_alloc) { }
Guard operator () () { return _synced_object(); } Guard operator () () { return _synced_object(); }

View File

@ -421,8 +421,7 @@ class Genode::Thread
/** /**
* Log trace event as defined in base/trace/events.h * Log trace event as defined in base/trace/events.h
*/ */
template <typename EVENT> static void trace(auto const *event) { _logger()->log(event); }
static void trace(EVENT const *event) { _logger()->log(event); }
/** /**
* Thread affinity * Thread affinity

View File

@ -160,8 +160,7 @@ class Genode::Trace::Simple_buffer
_head_entry()->mark(_Entry::HEAD); _head_entry()->mark(_Entry::HEAD);
} }
template <typename WRAP_FUNC> char *_reserve(size_t len, auto const &wrap_fn)
char *_reserve(size_t len, WRAP_FUNC && wrap)
{ {
if (_head_offset + sizeof(_Entry) + len <= _size) if (_head_offset + sizeof(_Entry) + len <= _size)
return _head_entry()->data; return _head_entry()->data;
@ -170,11 +169,10 @@ class Genode::Trace::Simple_buffer
if (_head_offset + sizeof(_Entry) <= _size) if (_head_offset + sizeof(_Entry) <= _size)
_head_entry()->mark(_Entry::PADDING); _head_entry()->mark(_Entry::PADDING);
return wrap(); return wrap_fn();
} }
template <typename WRAP_FUNC> void _commit(size_t len, auto const &wrap_fn)
void _commit(size_t len, WRAP_FUNC && wrap)
{ {
/* omit empty entries */ /* omit empty entries */
if (len == 0) if (len == 0)
@ -190,7 +188,7 @@ class Genode::Trace::Simple_buffer
/* advance head offset, wrap when next entry does not fit into buffer */ /* advance head offset, wrap when next entry does not fit into buffer */
_head_offset += sizeof(_Entry) + len; _head_offset += sizeof(_Entry) + len;
if (_head_offset + sizeof(_Entry) > _size) if (_head_offset + sizeof(_Entry) > _size)
wrap(); wrap_fn();
/* mark entry next to new entry as head */ /* mark entry next to new entry as head */
else if (_head_offset + sizeof(_Entry) <= _size) else if (_head_offset + sizeof(_Entry) <= _size)

View File

@ -77,9 +77,8 @@ struct Genode::Trace::Logger
/** /**
* Log event to trace buffer * Log event to trace buffer
*/ */
template <typename EVENT>
__attribute__((optimize("-fno-delete-null-pointer-checks"))) __attribute__((optimize("-fno-delete-null-pointer-checks")))
void log(EVENT const *event) void log(auto const *event)
{ {
if (!this || !_evaluate_control()) return; if (!this || !_evaluate_control()) return;

View File

@ -53,8 +53,8 @@ class Genode::Page_table_allocator
virtual ~Page_table_allocator() { } virtual ~Page_table_allocator() { }
template <typename TABLE, typename FN1, typename FN2> template <typename TABLE>
void with_table(addr_t phys_addr, FN1 && match_fn, FN2 no_match_fn) void with_table(addr_t phys_addr, auto const &match_fn, auto const &no_match_fn)
{ {
static_assert((sizeof(TABLE) == TABLE_SIZE), "unexpected size"); static_assert((sizeof(TABLE) == TABLE_SIZE), "unexpected size");
@ -108,8 +108,7 @@ class Genode::Page_table_allocator<TABLE_SIZE>::Array
Array() : _alloc((Table*)&_tables, (addr_t)&_tables, COUNT * TABLE_SIZE) {} Array() : _alloc((Table*)&_tables, (addr_t)&_tables, COUNT * TABLE_SIZE) {}
template <typename T> explicit Array(auto phys_addr)
explicit Array(T phys_addr)
: _alloc(_tables, phys_addr((void*)_tables), COUNT * TABLE_SIZE) { } : _alloc(_tables, phys_addr((void*)_tables), COUNT * TABLE_SIZE) { }
Page_table_allocator<TABLE_SIZE> & alloc() { return _alloc; } Page_table_allocator<TABLE_SIZE> & alloc() { return _alloc; }

View File

@ -73,8 +73,7 @@ struct Genode::Region_map : Interface
public: public:
template <typename T> Local_addr(auto ptr) : _ptr((void *)ptr) { }
Local_addr(T ptr) : _ptr((void *)ptr) { }
Local_addr() { } Local_addr() { }

View File

@ -225,14 +225,9 @@ class Genode::Vcpu_state
bool charged() const { return _charged; } bool charged() const { return _charged; }
template <typename FN> void with_state(auto const &fn) const { fn(_state); }
void with_state(FN const &fn) const
{
fn(_state);
}
template <typename FN> void charge(auto const &fn)
void charge(FN const &fn)
{ {
_charged = true; _charged = true;
fn(_state); fn(_state);

View File

@ -88,8 +88,7 @@ struct Genode::Trace::Session_client : Genode::Rpc_client<Genode::Trace::Session
struct For_each_subject_info_result { size_t count; size_t limit; }; struct For_each_subject_info_result { size_t count; size_t limit; };
template <typename FN> For_each_subject_info_result for_each_subject_info(auto const &fn)
For_each_subject_info_result for_each_subject_info(FN const &fn)
{ {
size_t const num_subjects = call<Rpc_subject_infos>(); size_t const num_subjects = call<Rpc_subject_infos>();
size_t const max_subjects = _argument_buffer.size / (sizeof(Subject_info) + sizeof(Subject_id)); size_t const max_subjects = _argument_buffer.size / (sizeof(Subject_info) + sizeof(Subject_id));

View File

@ -24,10 +24,9 @@ namespace Genode { namespace Trace { struct Connection; } }
struct Genode::Trace::Connection : Genode::Connection<Genode::Trace::Session>, struct Genode::Trace::Connection : Genode::Connection<Genode::Trace::Session>,
Genode::Trace::Session_client Genode::Trace::Session_client
{ {
template <typename FUNC> auto _retry(auto const &fn) -> decltype(fn())
auto _retry(FUNC func) -> decltype(func())
{ {
return retry_with_upgrade(Ram_quota{8*1024}, Cap_quota{2}, func); return retry_with_upgrade(Ram_quota{8*1024}, Cap_quota{2}, fn);
} }
/** /**
@ -60,8 +59,7 @@ struct Genode::Trace::Connection : Genode::Connection<Genode::Trace::Session>,
return Session_client::subjects(dst, dst_len); }); return Session_client::subjects(dst, dst_len); });
} }
template <typename FN> For_each_subject_info_result for_each_subject_info(auto const &fn)
For_each_subject_info_result for_each_subject_info(FN const &fn)
{ {
return _retry([&] () { return _retry([&] () {
return Session_client::for_each_subject_info(fn); }); return Session_client::for_each_subject_info(fn); });

View File

@ -99,26 +99,23 @@ class Genode::Array
* *
* \throw Index_out_of_bounds * \throw Index_out_of_bounds
*/ */
template<typename ... TAIL> void add(T obj, auto &&... tail)
void add(T obj, TAIL ... tail)
{ {
add(obj); add(obj);
add(tail...); add(tail...);
} }
template <typename FUNC> void for_each(auto const &fn)
void for_each(FUNC const &f)
{ {
for (unsigned idx = 0; idx < _count; idx++) for (unsigned idx = 0; idx < _count; idx++)
f(idx, _objs[idx]); fn(idx, _objs[idx]);
} }
template <typename FUNC> void for_each(auto const &fn) const
void for_each(FUNC const &f) const
{ {
for (unsigned idx = 0; idx < _count; idx++) { for (unsigned idx = 0; idx < _count; idx++) {
T const & obj = _objs[idx]; T const & obj = _objs[idx];
f(idx, obj); fn(idx, obj);
} }
} }
}; };

View File

@ -52,21 +52,19 @@ class Genode::Attempt
Attempt(Attempt const &) = default; Attempt(Attempt const &) = default;
Attempt &operator = (Attempt const &) = default; Attempt &operator = (Attempt const &) = default;
template <typename RET, typename ACCESS_FN, typename FAIL_FN> template <typename RET>
RET convert(ACCESS_FN const &access_fn, FAIL_FN const &fail_fn) const RET convert(auto const &access_fn, auto const &fail_fn) const
{ {
return _ok ? RET { access_fn(_result) } return _ok ? RET { access_fn(_result) }
: RET { fail_fn(_error) }; : RET { fail_fn(_error) };
} }
template <typename ACCESS_FN, typename FAIL_FN> void with_result(auto const &access_fn, auto const &fail_fn) const
void with_result(ACCESS_FN const &access_fn, FAIL_FN const &fail_fn) const
{ {
_ok ? access_fn(_result) : fail_fn(_error); _ok ? access_fn(_result) : fail_fn(_error);
} }
template <typename FAIL_FN> void with_error(auto const &fail_fn) const
void with_error(FAIL_FN const &fail_fn) const
{ {
if (!_ok) if (!_ok)
fail_fn(_error); fail_fn(_error);

View File

@ -168,14 +168,13 @@ struct Genode::Avl_node : Avl_node_base
/** /**
* Apply a functor (read-only) to every node within this subtree * Apply a functor (read-only) to every node within this subtree
* *
* \param functor function that takes a const NT reference * \param fn function that takes a const NT reference
*/ */
template <typename FUNC> void for_each(auto const &fn) const
void for_each(FUNC && functor) const
{ {
if (NT * l = child(Avl_node<NT>::LEFT)) l->for_each(functor); if (NT * l = child(Avl_node<NT>::LEFT)) l->for_each(fn);
functor(*static_cast<NT const *>(this)); fn(*static_cast<NT const *>(this));
if (NT * r = child(Avl_node<NT>::RIGHT)) r->for_each(functor); if (NT * r = child(Avl_node<NT>::RIGHT)) r->for_each(fn);
} }
}; };
@ -229,13 +228,12 @@ class Genode::Avl_tree : Avl_node<NT>
/** /**
* Apply a functor (read-only) to every node within the tree * Apply a functor (read-only) to every node within the tree
* *
* \param functor function that takes a const NT reference * \param fn function that takes a const NT reference
* *
* The iteration order corresponds to the order of the keys * The iteration order corresponds to the order of the keys
*/ */
template <typename FUNC> void for_each(auto const &fn) const {
void for_each(FUNC && functor) const { if (first()) first()->for_each(fn); }
if (first()) first()->for_each(functor); }
}; };
#endif /* _INCLUDE__UTIL__AVL_TREE_H_ */ #endif /* _INCLUDE__UTIL__AVL_TREE_H_ */

View File

@ -81,9 +81,9 @@ class Genode::Dictionary : Noncopyable
* matching dictionary element. If no maching element exists, * matching dictionary element. If no maching element exists,
* 'no_match_fn' is called without argument. * 'no_match_fn' is called without argument.
*/ */
template <typename FN1, typename FN2> template <typename FN>
auto with_element(NAME const &name, FN1 const &match_fn, FN2 const &no_match_fn) auto with_element(NAME const &name, FN const &match_fn, auto const &no_match_fn)
-> typename Trait::Functor<decltype(&FN1::operator())>::Return_type -> typename Trait::Functor<decltype(&FN::operator())>::Return_type
{ {
T *curr_ptr = _tree.first(); T *curr_ptr = _tree.first();
for (;;) { for (;;) {
@ -106,9 +106,9 @@ class Genode::Dictionary : Noncopyable
* matching dictionary element. If no maching element exists, * matching dictionary element. If no maching element exists,
* 'no_match_fn' is called without argument. * 'no_match_fn' is called without argument.
*/ */
template <typename FN1, typename FN2> template <typename FN>
auto with_element(NAME const &name, FN1 const &match_fn, FN2 const &no_match_fn) const auto with_element(NAME const &name, FN const &match_fn, auto const &no_match_fn) const
-> typename Trait::Functor<decltype(&FN1::operator())>::Return_type -> typename Trait::Functor<decltype(&FN::operator())>::Return_type
{ {
auto const_match_fn = [&] (T const &e) { return match_fn(e); }; auto const_match_fn = [&] (T const &e) { return match_fn(e); };
auto non_const_this = const_cast<Dictionary *>(this); auto non_const_this = const_cast<Dictionary *>(this);
@ -124,8 +124,7 @@ class Genode::Dictionary : Noncopyable
* This method is intended for the orderly destruction of a dictionary. * This method is intended for the orderly destruction of a dictionary.
* It allows for the consecutive destruction of all elements. * It allows for the consecutive destruction of all elements.
*/ */
template <typename FUNC> bool with_any_element(auto const &fn)
bool with_any_element(FUNC const &fn)
{ {
T *curr_ptr = _tree.first(); T *curr_ptr = _tree.first();
if (!curr_ptr) if (!curr_ptr)
@ -135,8 +134,7 @@ class Genode::Dictionary : Noncopyable
return true; return true;
} }
template <typename FN> void for_each(auto const &fn) const { _tree.for_each(fn); }
void for_each(FN const &fn) const { _tree.for_each(fn); }
bool exists(NAME const &name) const bool exists(NAME const &name) const
{ {

View File

@ -75,10 +75,9 @@ class Genode::Fifo
Fifo() { } Fifo() { }
/** /**
* Call 'func' of type 'void (QT&)' the head element * Call 'fn' of type 'void (QT&)' the head element
*/ */
template <typename FUNC> void head(auto const &fn) const { if (_head) fn(*_head); }
void head(FUNC const &func) const { if (_head) func(*_head); }
/** /**
* Remove element explicitly from queue * Remove element explicitly from queue
@ -130,25 +129,23 @@ class Genode::Fifo
} }
/** /**
* Call 'func' of type 'void (QT&)' for each element in order * Call 'fn' of type 'void (QT&)' for each element in order
*/ */
template <typename FUNC> void for_each(auto const &fn) const
void for_each(FUNC const &func) const
{ {
QT *elem = _head; QT *elem = _head;
while (elem != nullptr) { while (elem != nullptr) {
/* take the next pointer so 'func' cannot modify it */ /* take the next pointer so 'fn' cannot modify it */
QT *next = elem->Fifo::Element::_next;; QT *next = elem->Fifo::Element::_next;;
func(*elem); fn(*elem);
elem = next; elem = next;
} }
} }
/** /**
* Remove head and call 'func' of type 'void (QT&)' * Remove head and call 'fn' of type 'void (QT&)'
*/ */
template <typename FUNC> void dequeue(auto const &fn)
void dequeue(FUNC const &func)
{ {
QT *result = _head; QT *result = _head;
@ -165,7 +162,7 @@ class Genode::Fifo
result->Fifo::Element::_enqueued = false; result->Fifo::Element::_enqueued = false;
/* pass to caller */ /* pass to caller */
func(*result); fn(*result);
} }
} }
@ -173,13 +170,12 @@ class Genode::Fifo
* Remove all fifo elements * Remove all fifo elements
* *
* This method removes all elements in order and calls the lambda * This method removes all elements in order and calls the lambda
* 'func' of type 'void (QT&)' for each element. It is intended to be * 'fn' of type 'void (QT&)' for each element. It is intended to be
* used prior the destruction of the FIFO. * used prior the destruction of the FIFO.
*/ */
template <typename FUNC> void dequeue_all(auto const &fn)
void dequeue_all(FUNC const &func)
{ {
while (_head != nullptr) dequeue(func); while (_head != nullptr) dequeue(fn);
} }
}; };

View File

@ -122,8 +122,7 @@ class Genode::List_model : Noncopyable
/** /**
* Call functor 'fn' for each const element * Call functor 'fn' for each const element
*/ */
template <typename FN> void for_each(auto const &fn) const
void for_each(FN const &fn) const
{ {
for (Element const *e = _elements.first(); e; e = e->next()) for (Element const *e = _elements.first(); e; e = e->next())
fn(static_cast<ELEM const &>(*e)); fn(static_cast<ELEM const &>(*e));
@ -132,8 +131,7 @@ class Genode::List_model : Noncopyable
/** /**
* Call functor 'fn' for each non-const element * Call functor 'fn' for each non-const element
*/ */
template <typename FN> void for_each(auto const &fn)
void for_each(FN const &fn)
{ {
Element *next = nullptr; Element *next = nullptr;
for (Element *e = _elements.first(); e; e = next) { for (Element *e = _elements.first(); e; e = next) {
@ -150,8 +148,7 @@ class Genode::List_model : Noncopyable
* list-model elements are visited via recursive function calls * list-model elements are visited via recursive function calls
* instead of a 'for_each' loop. * instead of a 'for_each' loop.
*/ */
template <typename FN> void with_first(auto const &fn) const
void with_first(FN const &fn) const
{ {
if (Element const *e = _elements.first()) if (Element const *e = _elements.first())
fn(static_cast<ELEM const &>(*e)); fn(static_cast<ELEM const &>(*e));

View File

@ -18,8 +18,8 @@
namespace Genode { namespace Genode {
template <size_t, typename FUNC> template <size_t>
static inline void print_lines(char const *, size_t, FUNC const &); static inline void print_lines(char const *, size_t, auto const &);
} }
@ -30,7 +30,7 @@ namespace Genode {
* on the stack * on the stack
* \param string character buffer, not necessarily null-terminated * \param string character buffer, not necessarily null-terminated
* \param len number of characters to print * \param len number of characters to print
* \param func functor called for each line with 'char const *' as * \param fn functor called for each line with 'char const *' as
* argument * argument
* *
* In situations where a string is supplied by an untrusted client, we cannot * In situations where a string is supplied by an untrusted client, we cannot
@ -42,8 +42,8 @@ namespace Genode {
* The output stops when reaching the end of the buffer or when a null * The output stops when reaching the end of the buffer or when a null
* character is encountered. * character is encountered.
*/ */
template <Genode::size_t MAX_LINE_LEN, typename FUNC> template <Genode::size_t MAX_LINE_LEN>
void Genode::print_lines(char const *string, size_t len, FUNC const &func) void Genode::print_lines(char const *string, size_t len, auto const &fn)
{ {
/* skip leading line breaks */ /* skip leading line breaks */
for (; *string == '\n'; string++); for (; *string == '\n'; string++);
@ -89,7 +89,7 @@ void Genode::print_lines(char const *string, size_t len, FUNC const &func)
copy_cstring(line_buf, string, line_len - skip_char + 1); copy_cstring(line_buf, string, line_len - skip_char + 1);
/* process null-terminated string in buffer */ /* process null-terminated string in buffer */
func(line_buf); fn(line_buf);
/* move forward to the next sub-string to process */ /* move forward to the next sub-string to process */
string += line_len; string += line_len;

View File

@ -52,7 +52,7 @@ Genode::Reconstructible : Noncopyable
*/ */
bool _constructed = false; bool _constructed = false;
template <typename... ARGS> void _do_construct(ARGS &&... args) void _do_construct(auto &&... args)
{ {
construct_at<MT>(_space, args...); construct_at<MT>(_space, args...);
_constructed = true; _constructed = true;
@ -91,11 +91,7 @@ Genode::Reconstructible : Noncopyable
* The arguments are forwarded to the constructor of the embedded * The arguments are forwarded to the constructor of the embedded
* object. * object.
*/ */
template <typename... ARGS> Reconstructible(auto &&... args) { _do_construct(args...); }
Reconstructible(ARGS &&... args)
{
_do_construct(args...);
}
~Reconstructible() { destruct(); } ~Reconstructible() { destruct(); }
@ -105,8 +101,7 @@ Genode::Reconstructible : Noncopyable
* If the 'Reconstructible' already hosts a constructed object, the old * If the 'Reconstructible' already hosts a constructed object, the old
* object will be destructed first. * object will be destructed first.
*/ */
template <typename... ARGS> void construct(auto &&... args)
void construct(ARGS &&... args)
{ {
destruct(); destruct();
_do_construct(args...); _do_construct(args...);
@ -134,8 +129,7 @@ Genode::Reconstructible : Noncopyable
/** /**
* Construct or destruct volatile object according to 'condition' * Construct or destruct volatile object according to 'condition'
*/ */
template <typename... ARGS> void conditional(bool condition, auto &&... args)
void conditional(bool condition, ARGS &&... args)
{ {
if (condition && !constructed()) if (condition && !constructed())
construct(args...); construct(args...);

View File

@ -17,9 +17,9 @@
namespace Genode { namespace Genode {
template <typename EXC, typename FUNC, typename HANDLER> template <typename EXC>
auto retry(FUNC func, HANDLER handler, auto retry(auto const &fn, auto const &,
unsigned attempts = ~0U) -> decltype(func()); unsigned attempts = ~0U) -> decltype(fn());
} }
/** /**
@ -29,20 +29,20 @@ namespace Genode {
* is called and the function call is retried. * is called and the function call is retried.
* *
* \param EXC exception type to handle * \param EXC exception type to handle
* \param func functor to execute * \param fn functor to execute
* \param handler exception handler executed if 'func' raised an exception * \param exc_fn exception handler executed if 'fn' raised an exception
* of type 'EXC' * of type 'EXC'
* \param attempts number of attempts to execute 'func' before giving up * \param attempts number of attempts to execute 'func' before giving up
* and reflecting the exception 'EXC' to the caller. If not * and reflecting the exception 'EXC' to the caller. If not
* specified, attempt infinitely. * specified, attempt infinitely.
*/ */
template <typename EXC, typename FUNC, typename HANDLER> template <typename EXC>
auto Genode::retry(FUNC func, HANDLER handler, auto Genode::retry(auto const &fn, auto const &exc_fn,
unsigned attempts) -> decltype(func()) unsigned attempts) -> decltype(fn())
{ {
for (unsigned i = 0; attempts == ~0U || i < attempts; i++) for (unsigned i = 0; attempts == ~0U || i < attempts; i++)
try { return func(); } try { return fn(); }
catch (EXC) { handler(); } catch (EXC) { exc_fn(); }
throw EXC(); throw EXC();
} }

View File

@ -771,12 +771,12 @@ class Genode::String
* may fit perfectly into the buffer or may have been truncated. * may fit perfectly into the buffer or may have been truncated.
* In general, it would be safe to assume the latter. * In general, it would be safe to assume the latter.
*/ */
template <typename T, typename... TAIL> template <typename T>
String(T const &arg, TAIL &&... args) String(T const &head, auto &&... tail)
{ {
/* initialize string content */ /* initialize string content */
Local_output output(_buf); Local_output output(_buf);
Genode::print(output, arg, args...); Genode::print(output, head, tail...);
/* add terminating null */ /* add terminating null */
_buf[output.num_chars()] = 0; _buf[output.num_chars()] = 0;

View File

@ -296,23 +296,20 @@ class Genode::Xml_generator
public: public:
template <typename FUNC> Xml_generator(char *dst, size_t dst_len, char const *name, auto const &fn)
Xml_generator(char *dst, size_t dst_len,
char const *name, FUNC const &func)
: :
_out_buffer(dst, dst_len) _out_buffer(dst, dst_len)
{ {
if (dst) { if (dst) {
node(name, func); node(name, fn);
_out_buffer.append('\n'); _out_buffer.append('\n');
_out_buffer.append('\0'); _out_buffer.append('\0');
} }
} }
template <typename FUNC> void node(char const *name, auto const &fn = [] () { } )
void node(char const *name, FUNC const &func = [] () { } )
{ {
Node(*this, name, func); Node(*this, name, fn);
} }
void node(char const *name) { Node(*this, name, [] () { }); } void node(char const *name) { Node(*this, name, [] () { }); }
@ -394,8 +391,7 @@ class Genode::Xml_generator
* *
* This method must not be followed by calls of 'attribute'. * This method must not be followed by calls of 'attribute'.
*/ */
template <typename... ARGS> void append_content(auto &&... args)
void append_content(ARGS &&... args)
{ {
struct Node_output : Genode::Output struct Node_output : Genode::Output
{ {

View File

@ -156,8 +156,7 @@ class Genode::Xml_attribute
* Note that the content of the buffer is not null-terminated but * Note that the content of the buffer is not null-terminated but
* delimited by the size argument. * delimited by the size argument.
*/ */
template <typename FN> void with_raw_value(auto const &fn) const
void with_raw_value(FN const &fn) const
{ {
/* /*
* Skip leading quote of the '_value' to access the actual value. * Skip leading quote of the '_value' to access the actual value.
@ -173,8 +172,7 @@ class Genode::Xml_attribute
* false if attribute is invalid or value * false if attribute is invalid or value
* conversion failed * conversion failed
*/ */
template <typename T> bool value(auto &out) const
bool value(T &out) const
{ {
bool result = false; bool result = false;
@ -678,8 +676,7 @@ class Genode::Xml_node
/** /**
* Call functor 'fn' with the node data '(char const *, size_t)' * Call functor 'fn' with the node data '(char const *, size_t)'
*/ */
template <typename FN> void with_raw_node(auto const &fn) const
void with_raw_node(FN const &fn) const
{ {
char const *start_ptr = _tags.start.token().start(); char const *start_ptr = _tags.start.token().start();
fn(start_ptr, _tags.end.next_token().start() - start_ptr); fn(start_ptr, _tags.end.next_token().start() - start_ptr);
@ -693,8 +690,7 @@ class Genode::Xml_node
* *
* If the node has no content, the functor 'fn' is not called. * If the node has no content, the functor 'fn' is not called.
*/ */
template <typename FN> void with_raw_content(auto const &fn) const
void with_raw_content(FN const &fn) const
{ {
if (_tags.start.type() == Tag::EMPTY) if (_tags.start.type() == Tag::EMPTY)
return; return;
@ -844,8 +840,7 @@ class Genode::Xml_node
* The functor is called with the sub node as argument. * The functor is called with the sub node as argument.
* If no matching sub node exists, the functor is not called. * If no matching sub node exists, the functor is not called.
*/ */
template <typename FN> void with_optional_sub_node(char const *type, auto const &fn) const
void with_optional_sub_node(char const *type, FN const &fn) const
{ {
if (has_sub_node(type)) if (has_sub_node(type))
fn(sub_node(type)); fn(sub_node(type));
@ -855,22 +850,20 @@ class Genode::Xml_node
* Apply functor 'fn' to first sub node of specified type * Apply functor 'fn' to first sub node of specified type
* *
* The functor is called with the sub node as argument. * The functor is called with the sub node as argument.
* If no matching sub node exists, the functor 'fn_nexists' is called. * If no matching sub node exists, the functor 'missing_fn' is called.
*/ */
template <typename FN, typename FN_NEXISTS> void with_sub_node(char const *type, auto const &fn, auto const &missing_fn) const
void with_sub_node(char const *type, FN const &fn, FN_NEXISTS const &fn_nexists) const
{ {
if (has_sub_node(type)) if (has_sub_node(type))
fn(sub_node(type)); fn(sub_node(type));
else else
fn_nexists(); missing_fn();
} }
/** /**
* Execute functor 'fn' for each sub node of specified type * Execute functor 'fn' for each sub node of specified type
*/ */
template <typename FN> void for_each_sub_node(char const *type, auto const &fn) const
void for_each_sub_node(char const *type, FN const &fn) const
{ {
if (!has_sub_node(type)) if (!has_sub_node(type))
return; return;
@ -887,8 +880,7 @@ class Genode::Xml_node
/** /**
* Execute functor 'fn' for each sub node * Execute functor 'fn' for each sub node
*/ */
template <typename FN> void for_each_sub_node(auto const &fn) const
void for_each_sub_node(FN const &fn) const
{ {
for_each_sub_node(nullptr, fn); for_each_sub_node(nullptr, fn);
} }
@ -993,8 +985,7 @@ class Genode::Xml_node
/** /**
* Execute functor 'fn' for each attribute * Execute functor 'fn' for each attribute
*/ */
template <typename FN> void for_each_attribute(auto const &fn) const
void for_each_attribute(FN const &fn) const
{ {
if (!_tags.start.has_attribute()) if (!_tags.start.has_attribute())
return; return;

View File

@ -105,13 +105,12 @@ struct Genode::Vm_connection : Connection<Vm_session>, Rpc_client<Vm_session>
Rpc_client<Vm_session>(cap()) Rpc_client<Vm_session>(cap())
{ } { }
template <typename FUNC> auto with_upgrade(auto const &fn) -> decltype(fn())
auto with_upgrade(FUNC func) -> decltype(func())
{ {
return Genode::retry<Genode::Out_of_ram>( return Genode::retry<Genode::Out_of_ram>(
[&] () { [&] () {
return Genode::retry<Genode::Out_of_caps>( return Genode::retry<Genode::Out_of_caps>(
[&] () { return func(); }, [&] () { return fn(); },
[&] () { this->upgrade_caps(2); }); [&] () { this->upgrade_caps(2); });
}, },
[&] () { this->upgrade_ram(4096); } [&] () { this->upgrade_ram(4096); }