Allow RPC arguments w/o default constructor

Fixes #2150
This commit is contained in:
Edgard Schmidt 2016-10-08 04:37:32 +02:00 committed by Christian Helmuth
parent 6a24d70120
commit f97e0f3fa0
8 changed files with 198 additions and 164 deletions

View File

@ -24,6 +24,9 @@ long Test::cap_void_manual(Genode::Native_capability dst,
Genode::Native_capability arg1,
Genode::addr_t &local_reply)
{
if (!arg1.valid())
return Genode::Rpc_exception_code::INVALID_OBJECT;
Genode::Thread * myself = Genode::Thread::myself();
Nova::Utcb *utcb = reinterpret_cast<Nova::Utcb *>(myself->utcb());
@ -38,9 +41,6 @@ long Test::cap_void_manual(Genode::Native_capability dst,
utcb->msg[1] = 0;
utcb->set_msg_word(2);
if (!arg1.valid())
return Genode::Rpc_exception_code::INVALID_OBJECT;
Nova::Crd crd = Genode::Capability_space::crd(arg1);
if (!utcb->append_item(crd, 0, false, false, false))
return Genode::Rpc_exception_code::INVALID_OBJECT;
@ -50,7 +50,7 @@ long Test::cap_void_manual(Genode::Native_capability dst,
/* restore original receive window */
utcb->crd_rcv = orig_crd;
local_reply = utcb->msg[2];
return (res == Nova::NOVA_OK && utcb->msg_words() == 3)
local_reply = utcb->msg[1];
return (res == Nova::NOVA_OK && utcb->msg_words() == 3 && utcb->msg[2])
? utcb->msg[0] : Genode::Rpc_exception_code::INVALID_OBJECT;
}

View File

@ -157,10 +157,12 @@ void test_revoke(Genode::Env &env)
Genode::Native_capability copy_session_cap = Capability_space::import(local_name);
local_name = Native_thread::INVALID_INDEX;
rpc = Test::cap_void_manual(copy_session_cap, copy_session_cap, local_name);
if (rpc != Genode::Rpc_exception_code::SUCCESS ||
local_name == (addr_t)copy_session_cap.local_name() ||
local_name == (addr_t)Native_thread::INVALID_INDEX)
local_name == (addr_t)Native_thread::INVALID_INDEX ||
local_name == (addr_t)session_cap.local_name())
{
failed ++;
error("test_revoke ipc call failed ", Hex(rpc));

View File

@ -115,8 +115,7 @@ class Genode::Capability : public Untyped_capability
* Perform RPC call, arguments passed a as nested 'Ref_tuple' object
*/
template <typename IF>
void _call(typename IF::Client_args &args,
typename IF::Ret_type &ret) const;
typename IF::Ret_type _call(typename IF::Client_args &args) const;
/**
* Shortcut for querying argument types used in 'call' methods
@ -137,27 +136,6 @@ class Genode::Capability : public Untyped_capability
return cap;
}
/**
* Wrapper for the return type instantiated by 'call' overloads
*
* Each 'call' overload creates an instance of the return value
* type as local variable. A reference to this variable is passed
* to the '_call' method, which will assign its value. Even
* though the variable does not need to be initialized prior the
* call of '_call', the GCC will still complain "warning: ret may
* be used uninitialized in this function". Wrapping the return
* value in a struct silences the compiler.
*/
template <typename IF>
struct Return
{
typedef typename Trait::Call_return<typename IF::Ret_type>::Type
Return_type;
volatile Return_type _value;
Return_type &value() { return *(Return_type *)(&_value); }
};
public:
typedef RPC_INTERFACE Rpc_interface;
@ -185,9 +163,7 @@ class Genode::Capability : public Untyped_capability
call() const
{
Meta::Empty e;
Return<IF> ret;
_call<IF>(e, ret.value());
return ret.value();
return _call<IF>(e);
}
template <typename IF>
@ -196,9 +172,7 @@ class Genode::Capability : public Untyped_capability
{
Meta::Empty e;
typename IF::Client_args args(v1, e);
Return<IF> ret;
_call<IF>(args, ret.value());
return ret.value();
return _call<IF>(args);
}
template <typename IF>
@ -207,9 +181,7 @@ class Genode::Capability : public Untyped_capability
{
Meta::Empty e;
typename IF::Client_args args(v1, v2, e);
Return<IF> ret;
_call<IF>(args, ret.value());
return ret.value();
return _call<IF>(args);
}
template <typename IF>
@ -219,9 +191,7 @@ class Genode::Capability : public Untyped_capability
{
Meta::Empty e;
typename IF::Client_args args(v1, v2, v3, e);
Return<IF> ret;
_call<IF>(args, ret.value());
return ret.value();
return _call<IF>(args);
}
template <typename IF>
@ -231,9 +201,7 @@ class Genode::Capability : public Untyped_capability
{
Meta::Empty e;
typename IF::Client_args args(v1, v2, v3, v4, e);
Return<IF> ret;
_call<IF>(args, ret.value());
return ret.value();
return _call<IF>(args);
}
template <typename IF>
@ -244,9 +212,7 @@ class Genode::Capability : public Untyped_capability
{
Meta::Empty e;
typename IF::Client_args args(v1, v2, v3, v4, v5, e);
Return<IF> ret;
_call<IF>(args, ret.value());
return ret.value();
return _call<IF>(args);
}
template <typename IF>
@ -257,9 +223,7 @@ class Genode::Capability : public Untyped_capability
{
Meta::Empty e;
typename IF::Client_args args(v1, v2, v3, v4, v5, v6, e);
Return<IF> ret;
_call<IF>(args, ret.value());
return ret.value();
return _call<IF>(args);
}
template <typename IF>
@ -271,9 +235,7 @@ class Genode::Capability : public Untyped_capability
{
Meta::Empty e;
typename IF::Client_args args(v1, v2, v3, v4, v5, v6, v7, e);
Return<IF> ret;
_call<IF>(args, ret.value());
return ret.value();
return _call<IF>(args);
}
};

View File

@ -17,6 +17,7 @@
#include <base/ipc_msgbuf.h>
#include <base/rpc_args.h>
#include <base/log.h>
#include <util/meta.h>
namespace Genode {
@ -65,9 +66,15 @@ class Genode::Ipc_unmarshaller : Noncopyable
template <typename IT>
void extract(Capability<IT> &typed_cap)
{
Native_capability untyped_cap;
extract(untyped_cap);
typed_cap = reinterpret_cap_cast<IT>(untyped_cap);
typed_cap = extract(Meta::Overload_selector<Capability<IT> >());
}
template<typename IT>
Capability<IT> extract(Meta::Overload_selector<Capability<IT> >)
{
Native_capability untyped_cap =
extract(Meta::Overload_selector<Native_capability>());
return reinterpret_cap_cast<IT>(untyped_cap);
}
/**
@ -75,9 +82,15 @@ class Genode::Ipc_unmarshaller : Noncopyable
*/
void extract(Native_capability &cap)
{
cap = _read_cap_index < _rcv_msg.used_caps()
? _rcv_msg.cap(_read_cap_index) : Native_capability();
cap = extract(Meta::Overload_selector<Native_capability>());
}
Native_capability extract(Meta::Overload_selector<Native_capability>)
{
Native_capability cap = _read_cap_index < _rcv_msg.used_caps()
? _rcv_msg.cap(_read_cap_index) : Native_capability();
_read_cap_index++;
return cap;
}
/**
@ -86,8 +99,6 @@ class Genode::Ipc_unmarshaller : Noncopyable
template <size_t SIZE>
void extract(Rpc_in_buffer<SIZE> &b)
{
size_t size = 0;
extract(size);
b = Rpc_in_buffer<SIZE>(0, 0);
/*
@ -96,13 +107,23 @@ class Genode::Ipc_unmarshaller : Noncopyable
* Note: The addr of the Rpc_in_buffer_base is a null pointer when this
* condition triggers.
*/
try {
b = extract(Meta::Overload_selector<Rpc_in_buffer<SIZE> >());
} catch (Ipc_error) { }
}
template<size_t SIZE>
Rpc_in_buffer<SIZE> extract(Meta::Overload_selector<Rpc_in_buffer<SIZE> >)
{
size_t size = extract(Meta::Overload_selector<size_t>());
if (_read_offset + size > _rcv_buf_size) {
error("message buffer overrun");
return;
throw Ipc_error();
}
b = Rpc_in_buffer<SIZE>(&_rcv_buf[_read_offset], size);
Rpc_in_buffer<SIZE> buf(&_rcv_buf[_read_offset], size);
_read_offset += align_natural(size);
return buf;
}
/**
@ -110,15 +131,23 @@ class Genode::Ipc_unmarshaller : Noncopyable
*/
template <typename T>
void extract(T &value)
{
value = extract(Meta::Overload_selector<T>());
}
template <typename T>
T extract(Meta::Overload_selector<T>)
{
/* check receive buffer range */
if (_read_offset + sizeof(T) > _rcv_buf_size) return;
if (_read_offset + sizeof(T) > _rcv_buf_size) throw Ipc_error();
/* return value from receive buffer */
value = *reinterpret_cast<T *>(&_rcv_buf[_read_offset]);
T value = *reinterpret_cast<T *>(&_rcv_buf[_read_offset]);
/* increment read pointer to next dword-aligned value */
_read_offset += align_natural(sizeof(T));
return value;
}
Ipc_unmarshaller(Msgbuf_base &rcv_msg) : _rcv_msg(rcv_msg) { }

View File

@ -43,9 +43,9 @@
typedef ::Genode::Trait::Call_return<ret_type>::Type Ret_type; \
\
template <typename SERVER, typename RET> \
static void serve(SERVER &server, Server_args &args, RET &ret) { \
::Genode::Meta::call_member<RET, SERVER, Server_args> \
(ret, server, args, &SERVER::func_name); } \
static RET serve(SERVER &server, Server_args &args) { \
return ::Genode::Meta::call_member<RET, SERVER, Server_args> \
(server, args, &SERVER::func_name); } \
\
static const char* name() { return #func_name; } \
};

View File

@ -107,8 +107,8 @@ namespace Genode {
template <typename RPC_INTERFACE>
template <typename IF>
void Capability<RPC_INTERFACE>::
_call(typename IF::Client_args &args, typename IF::Ret_type &ret) const
typename IF::Ret_type Capability<RPC_INTERFACE>::
_call(typename IF::Client_args &args) const
{
/**
* Message buffer for RPC message
@ -144,7 +144,6 @@ namespace Genode {
throw Ipc_error();
Ipc_unmarshaller unmarshaller(reply_buf);
unmarshaller.extract(ret);
{
Trace::Rpc_returned trace_event(IF::name(), reply_buf);
@ -156,6 +155,10 @@ namespace Genode {
/* reflect callee-side exception at the caller */
_check_for_exceptions(exception_code,
Meta::Overload_selector<typename IF::Exceptions>());
/* the return value does only exist if no exception was thrown */
Meta::Overload_selector<typename IF::Ret_type> ret_overloader;
return unmarshaller.extract(ret_overloader);
}
}

View File

@ -63,15 +63,44 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
protected:
template <typename ARG_LIST>
void _read_args(Ipc_unmarshaller &msg, ARG_LIST &args)
ARG_LIST _read_args(Ipc_unmarshaller &msg,
Meta::Overload_selector<ARG_LIST>)
{
if (Trait::Rpc_direction<typename ARG_LIST::Head>::Type::IN)
msg.extract(args._1);
typename Trait::Rpc_direction<typename ARG_LIST::Head>::Type direction;
typedef typename ARG_LIST::Stored_head Arg;
Arg arg = _read_arg<Arg>(msg, direction);
_read_args(msg, args._2);
Meta::Overload_selector<typename ARG_LIST::Tail> tail_selector;
typename ARG_LIST::Tail subsequent_args = _read_args(msg,
tail_selector);
ARG_LIST args { arg, subsequent_args };
return args;
}
void _read_args(Ipc_unmarshaller &, Meta::Empty) { }
Meta::Empty _read_args(Ipc_unmarshaller &msg,
Meta::Overload_selector<Meta::Empty>)
{
return Meta::Empty();
}
template <typename ARG>
ARG _read_arg(Ipc_unmarshaller &msg, Rpc_arg_in)
{
return msg.extract(Meta::Overload_selector<ARG>());
}
template <typename ARG>
ARG _read_arg(Ipc_unmarshaller &msg, Rpc_arg_inout)
{
return _read_arg<ARG>(msg, Rpc_arg_in());
}
template <typename ARG>
ARG _read_arg(Ipc_unmarshaller &msg, Rpc_arg_out)
{
return ARG();
}
template <typename ARG_LIST>
void _write_results(Msgbuf_base &msg, ARG_LIST &args)
@ -85,28 +114,34 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
void _write_results(Msgbuf_base &, Meta::Empty) { }
template <typename RPC_FUNCTION, typename EXC_TL>
Rpc_exception_code _do_serve(typename RPC_FUNCTION::Server_args &args,
typename RPC_FUNCTION::Ret_type &ret,
Meta::Overload_selector<RPC_FUNCTION, EXC_TL>)
typename RPC_FUNCTION::Ret_type
_do_serve(typename RPC_FUNCTION::Server_args &args,
Meta::Overload_selector<RPC_FUNCTION, EXC_TL>)
{
enum { EXCEPTION_CODE = Rpc_exception_code::EXCEPTION_BASE
- Meta::Length<EXC_TL>::Value };
try {
typedef typename EXC_TL::Tail Exc_tail;
return _do_serve(args, ret,
return _do_serve(args,
Meta::Overload_selector<RPC_FUNCTION, Exc_tail>());
} catch (typename EXC_TL::Head) {
return Rpc_exception_code(EXCEPTION_CODE);
/**
* By passing the exception code through an exception we ensure that
* a return value is only returned if it exists. This way, the return
* type does not have to be default-constructible.
*/
throw Rpc_exception_code(EXCEPTION_CODE);
}
}
template <typename RPC_FUNCTION>
Rpc_exception_code _do_serve(typename RPC_FUNCTION::Server_args &args,
typename RPC_FUNCTION::Ret_type &ret,
Meta::Overload_selector<RPC_FUNCTION, Meta::Empty>)
typename RPC_FUNCTION::Ret_type
_do_serve(typename RPC_FUNCTION::Server_args &args,
Meta::Overload_selector<RPC_FUNCTION, Meta::Empty>)
{
RPC_FUNCTION::serve(*static_cast<SERVER *>(this), args, ret);
return Rpc_exception_code(Rpc_exception_code::SUCCESS);
typedef typename RPC_FUNCTION::Ret_type Ret_type;
SERVER *me = static_cast<SERVER *>(this);
return RPC_FUNCTION::template serve<SERVER, Ret_type>(*me, args);
}
template <typename RPC_FUNCTIONS_TO_CHECK>
@ -120,10 +155,10 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
if (opcode.value == Index_of<Rpc_functions, This_rpc_function>::Value) {
typename This_rpc_function::Server_args args{};
/* read arguments from incoming message */
_read_args(in, args);
typedef typename This_rpc_function::Server_args Server_args;
Meta::Overload_selector<Server_args> arg_selector;
Server_args args = _read_args(in, arg_selector);
{
Trace::Rpc_dispatch trace_event(This_rpc_function::name());
@ -134,22 +169,29 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
* 'This_rpc_function' and the list of its exceptions to
* select the overload.
*/
typedef typename This_rpc_function::Exceptions Exceptions;
typename This_rpc_function::Ret_type ret { };
Rpc_exception_code
exc(_do_serve(args, ret,
Overload_selector<This_rpc_function, Exceptions>()));
typedef typename This_rpc_function::Ret_type Ret_type;
Rpc_exception_code exc(Rpc_exception_code::SUCCESS);
try {
typedef typename This_rpc_function::Exceptions Exceptions;
Overload_selector<This_rpc_function, Exceptions> overloader;
Ret_type ret = _do_serve(args, overloader);
out.insert(ret);
_write_results(out, args);
out.insert(ret);
} catch (Rpc_exception_code thrown) {
/**
* Output arguments may be modified although an exception was thrown.
* However, a return value does not exist. So we do not insert one.
*/
_write_results(out, args);
exc = thrown;
}
{
Trace::Rpc_reply trace_event(This_rpc_function::name());
}
/* write results to outgoing message */
_write_results(out, args);
return exc;
}

View File

@ -291,17 +291,26 @@ namespace Genode {
/**
* Tuple holding raw (plain old) data
*
* Has to be an aggregate type to allow non-default-constructible RPC
* arguments. But aggregate types must not derive from a base class in
* C++11. So we do not derive from Meta::Type_tuple although it is an
* empty class.
*/
template <typename HEAD, typename TAIL>
struct Pod_tuple : public Type_tuple<HEAD, TAIL>
struct Pod_tuple
{
typename Trait::Pod<HEAD>::Type _1;
typename Trait::Pod<TAIL>::Type _2;
typedef typename Trait::Pod<HEAD>::Type Stored_head;
Stored_head _1;
TAIL _2;
typedef HEAD Head;
typedef TAIL Tail;
/**
* Accessor for requesting the data reference to '_1'
*/
typename Trait::Pod<HEAD>::Type &get() { return _1; }
Stored_head &get() { return _1; }
};
/**
@ -313,32 +322,18 @@ namespace Genode {
* function returns a pointer to the stored copy.
*/
template <typename HEAD, typename TAIL>
struct Pod_tuple<HEAD *, TAIL> : public Type_tuple<HEAD *, TAIL>
struct Pod_tuple<HEAD *, TAIL>
{
typename Trait::Non_reference<HEAD>::Type _1;
typename Trait::Non_reference<TAIL>::Type _2;
typedef typename Trait::Non_reference<HEAD>::Type Stored_head;
Stored_head _1;
TAIL _2;
typedef HEAD* Head;
typedef TAIL Tail;
HEAD *get() { return &_1; }
};
template <typename T1, typename T2, typename T3>
struct Pod_tuple_3 : public Pod_tuple<T1, Pod_tuple<T2, T3> > { };
template <typename T1, typename T2, typename T3, typename T4>
struct Pod_tuple_4 : public Pod_tuple<T1, Pod_tuple_3<T2, T3, T4> > { };
template <typename T1, typename T2, typename T3, typename T4, typename T5>
struct Pod_tuple_5 : public Pod_tuple<T1, Pod_tuple_4<T2, T3, T4, T5> > { };
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
struct Pod_tuple_6 : public Pod_tuple<T1, Pod_tuple_5<T2, T3, T4, T5, T6> > { };
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
struct Pod_tuple_7 : public Pod_tuple<T1, Pod_tuple_6<T2, T3, T4, T5, T6, T7> > { };
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
struct Pod_tuple_8 : public Pod_tuple<T1, Pod_tuple_7<T2, T3, T4, T5, T6, T7, T8> > { };
/*************************************************************************
** Support for representing function arguments in a normalized fashion **
@ -409,22 +404,23 @@ namespace Genode {
struct Pod_args<T1, Void> { typedef Pod_tuple<T1, Empty> Type; };
template <typename T1, typename T2>
struct Pod_args<T1, T2, Void> { typedef Pod_tuple_3<T1, T2, Empty> Type; };
struct Pod_args<T1, T2, Void> { typedef Pod_tuple<T1, typename Pod_args<T2, Void>::Type> Type; };
template <typename T1, typename T2, typename T3>
struct Pod_args<T1, T2, T3, Void> { typedef Pod_tuple_4<T1, T2, T3, Empty> Type; };
struct Pod_args<T1, T2, T3, Void> { typedef Pod_tuple<T1, typename Pod_args<T2, T3, Void>::Type> Type; };
template <typename T1, typename T2, typename T3, typename T4>
struct Pod_args<T1, T2, T3, T4, Void> { typedef Pod_tuple_5<T1, T2, T3, T4, Empty> Type; };
struct Pod_args<T1, T2, T3, T4, Void> { typedef Pod_tuple<T1, typename Pod_args<T2, T3, T4, Void>::Type> Type; };
template <typename T1, typename T2, typename T3, typename T4, typename T5>
struct Pod_args<T1, T2, T3, T4, T5, Void> { typedef Pod_tuple_6<T1, T2, T3, T4, T5, Empty> Type; };
struct Pod_args<T1, T2, T3, T4, T5, Void> { typedef Pod_tuple<T1, typename Pod_args<T2, T3, T4, T5, Void>::Type> Type; };
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
struct Pod_args<T1, T2, T3, T4, T5, T6, Void> { typedef Pod_tuple_7<T1, T2, T3, T4, T5, T6, Empty> Type; };
struct Pod_args<T1, T2, T3, T4, T5, T6, Void> { typedef Pod_tuple<T1, typename Pod_args<T2, T3, T4, T5, T6, Void>::Type> Type; };
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
struct Pod_args<T1, T2, T3, T4, T5, T6, T7, Void> { typedef Pod_tuple_8<T1, T2, T3, T4, T5, T6, T7, Empty> Type; };
struct Pod_args<T1, T2, T3, T4, T5, T6, T7, Void> { typedef Pod_tuple<T1, typename Pod_args<T2, T3, T4, T5, T6, T7, Void>::Type> Type; };
/**
* Helper for calling member functions via a uniform interface
@ -453,114 +449,114 @@ namespace Genode {
*/
template <typename RET_TYPE, typename SERVER, typename ARGS>
static inline void call_member(RET_TYPE &ret, SERVER &server, ARGS &,
static inline RET_TYPE call_member(SERVER &server, ARGS &,
RET_TYPE (SERVER::*func)())
{ ret = (server.*func)(); }
{ return (server.*func)(); }
template <typename RET_TYPE, typename SERVER, typename ARGS>
static inline void call_member(RET_TYPE &ret, SERVER &server, ARGS &,
static inline RET_TYPE call_member(SERVER &server, ARGS &,
RET_TYPE (SERVER::*func)() const)
{ ret = (server.*func)(); }
{ return (server.*func)(); }
template <typename RET_TYPE, typename SERVER, typename ARGS>
static inline void call_member(Meta::Empty &, SERVER &server, ARGS &,
static inline RET_TYPE call_member(SERVER &server, ARGS &,
void (SERVER::*func)())
{ (server.*func)(); }
{ (server.*func)(); return Empty(); }
template <typename RET_TYPE, typename SERVER, typename ARGS>
static inline void call_member(Meta::Empty &, SERVER &server, ARGS &,
static inline RET_TYPE call_member(SERVER &server, ARGS &,
void (SERVER::*func)() const)
{ (server.*func)(); }
{ (server.*func)(); return Empty(); }
/* 1 */
template <typename RET_TYPE, typename SERVER, typename ARGS>
static inline void call_member(RET_TYPE &ret, SERVER &server, ARGS &args,
static inline RET_TYPE call_member(SERVER &server, ARGS &args,
RET_TYPE (SERVER::*func)(typename Type_at<ARGS, 0>::Type))
{ ret = (server.*func)(args.get()); }
{ return (server.*func)(args.get()); }
template <typename RET_TYPE, typename SERVER, typename ARGS>
static inline void call_member(Meta::Empty &, SERVER &server, ARGS &args,
static inline RET_TYPE call_member(SERVER &server, ARGS &args,
void (SERVER::*func)(typename Type_at<ARGS, 0>::Type))
{ (server.*func)(args.get()); }
{ (server.*func)(args.get()); return Empty(); }
/* 2 */
template <typename RET_TYPE, typename SERVER, typename ARGS>
static inline void call_member(RET_TYPE &ret, SERVER &server, ARGS &args,
static inline RET_TYPE call_member(SERVER &server, ARGS &args,
RET_TYPE (SERVER::*func)(typename Type_at<ARGS, 0>::Type,
typename Type_at<ARGS, 1>::Type))
{ ret = (server.*func)(args.get(), args._2.get()); }
{ return (server.*func)(args.get(), args._2.get()); }
template <typename RET_TYPE, typename SERVER, typename ARGS>
static inline void call_member(Meta::Empty &, SERVER &server, ARGS &args,
static inline RET_TYPE call_member(SERVER &server, ARGS &args,
void (SERVER::*func)(typename Type_at<ARGS, 0>::Type,
typename Type_at<ARGS, 1>::Type))
{ (server.*func)(args.get(), args._2.get()); }
{ (server.*func)(args.get(), args._2.get()); return Empty(); }
/* 3 */
template <typename RET_TYPE, typename SERVER, typename ARGS>
static inline void call_member(RET_TYPE &ret, SERVER &server, ARGS &args,
static inline RET_TYPE call_member(SERVER &server, ARGS &args,
RET_TYPE (SERVER::*func)(typename Type_at<ARGS, 0>::Type,
typename Type_at<ARGS, 1>::Type,
typename Type_at<ARGS, 2>::Type))
{ ret = (server.*func)(args.get(), args._2.get(), args._2._2.get()); }
{ return (server.*func)(args.get(), args._2.get(), args._2._2.get()); }
template <typename RET_TYPE, typename SERVER, typename ARGS>
static inline void call_member(Meta::Empty &, SERVER &server, ARGS &args,
static inline RET_TYPE call_member(SERVER &server, ARGS &args,
void (SERVER::*func)(typename Type_at<ARGS, 0>::Type,
typename Type_at<ARGS, 1>::Type,
typename Type_at<ARGS, 2>::Type))
{ (server.*func)(args.get(), args._2.get(), args._2._2.get()); }
{ (server.*func)(args.get(), args._2.get(), args._2._2.get()); return Empty(); }
/* 4 */
template <typename RET_TYPE, typename SERVER, typename ARGS>
static inline void call_member(RET_TYPE &ret, SERVER &server, ARGS &args,
static inline RET_TYPE call_member(SERVER &server, ARGS &args,
RET_TYPE (SERVER::*func)(typename Type_at<ARGS, 0>::Type,
typename Type_at<ARGS, 1>::Type,
typename Type_at<ARGS, 2>::Type,
typename Type_at<ARGS, 3>::Type))
{ ret = (server.*func)(args.get(), args._2.get(), args._2._2.get(), args._2._2._2.get()); }
{ return (server.*func)(args.get(), args._2.get(), args._2._2.get(), args._2._2._2.get()); }
template <typename RET_TYPE, typename SERVER, typename ARGS>
static inline void call_member(Meta::Empty &, SERVER &server, ARGS &args,
static inline RET_TYPE call_member(SERVER &server, ARGS &args,
void (SERVER::*func)(typename Type_at<ARGS, 0>::Type,
typename Type_at<ARGS, 1>::Type,
typename Type_at<ARGS, 2>::Type,
typename Type_at<ARGS, 3>::Type))
{ (server.*func)(args.get(), args._2.get(), args._2._2.get(), args._2._2._2.get()); }
{ (server.*func)(args.get(), args._2.get(), args._2._2.get(), args._2._2._2.get()); return Empty(); }
/* 5 */
template <typename RET_TYPE, typename SERVER, typename ARGS>
static inline void call_member(RET_TYPE &ret, SERVER &server, ARGS &args,
static inline RET_TYPE call_member(SERVER &server, ARGS &args,
RET_TYPE (SERVER::*func)(typename Type_at<ARGS, 0>::Type,
typename Type_at<ARGS, 1>::Type,
typename Type_at<ARGS, 2>::Type,
typename Type_at<ARGS, 3>::Type,
typename Type_at<ARGS, 4>::Type))
{ ret = (server.*func)(args.get(), args._2.get(), args._2._2.get(), args._2._2._2.get(), args._2._2._2._2.get()); }
{ return (server.*func)(args.get(), args._2.get(), args._2._2.get(), args._2._2._2.get(), args._2._2._2._2.get()); }
template <typename RET_TYPE, typename SERVER, typename ARGS>
static inline void call_member(Meta::Empty &, SERVER &server, ARGS &args,
static inline RET_TYPE call_member(SERVER &server, ARGS &args,
void (SERVER::*func)(typename Type_at<ARGS, 0>::Type,
typename Type_at<ARGS, 1>::Type,
typename Type_at<ARGS, 2>::Type,
typename Type_at<ARGS, 3>::Type,
typename Type_at<ARGS, 4>::Type))
{ (server.*func)(args.get(), args._2.get(), args._2._2.get(), args._2._2._2.get(), args._2._2._2._2.get()); }
{ (server.*func)(args.get(), args._2.get(), args._2._2.get(), args._2._2._2.get(), args._2._2._2._2.get()); return Empty(); }
/* 6 */
template <typename RET_TYPE, typename SERVER, typename ARGS>
static inline void call_member(RET_TYPE &ret, SERVER &server, ARGS &args,
static inline RET_TYPE call_member(SERVER &server, ARGS &args,
RET_TYPE (SERVER::*func)(typename Type_at<ARGS, 0>::Type,
typename Type_at<ARGS, 1>::Type,
typename Type_at<ARGS, 2>::Type,
typename Type_at<ARGS, 3>::Type,
typename Type_at<ARGS, 4>::Type,
typename Type_at<ARGS, 5>::Type))
{ ret = (server.*func)(args.get(), args._2.get(), args._2._2.get(), args._2._2._2.get(),
{ return (server.*func)(args.get(), args._2.get(), args._2._2.get(), args._2._2._2.get(),
args._2._2._2._2.get(), args._2._2._2._2._2.get()); }
template <typename RET_TYPE, typename SERVER, typename ARGS>
static inline void call_member(Meta::Empty &, SERVER &server, ARGS &args,
static inline RET_TYPE call_member(SERVER &server, ARGS &args,
void (SERVER::*func)(typename Type_at<ARGS, 0>::Type,
typename Type_at<ARGS, 1>::Type,
typename Type_at<ARGS, 2>::Type,
@ -568,11 +564,11 @@ namespace Genode {
typename Type_at<ARGS, 4>::Type,
typename Type_at<ARGS, 5>::Type))
{ (server.*func)(args.get(), args._2.get(), args._2._2.get(), args._2._2._2.get(),
args._2._2._2._2.get(), args._2._2._2._2._2.get()); }
args._2._2._2._2.get(), args._2._2._2._2._2.get()); return Empty(); }
/* 7 */
template <typename RET_TYPE, typename SERVER, typename ARGS>
static inline void call_member(RET_TYPE &ret, SERVER &server, ARGS &args,
static inline RET_TYPE call_member(SERVER &server, ARGS &args,
RET_TYPE (SERVER::*func)(typename Type_at<ARGS, 0>::Type,
typename Type_at<ARGS, 1>::Type,
typename Type_at<ARGS, 2>::Type,
@ -580,11 +576,11 @@ namespace Genode {
typename Type_at<ARGS, 4>::Type,
typename Type_at<ARGS, 5>::Type,
typename Type_at<ARGS, 6>::Type))
{ ret = (server.*func)(args.get(), args._2.get(), args._2._2.get(), args._2._2._2.get(),
{ return (server.*func)(args.get(), args._2.get(), args._2._2.get(), args._2._2._2.get(),
args._2._2._2._2.get(), args._2._2._2._2._2.get(), args._2._2._2._2._2._2.get()); }
template <typename RET_TYPE, typename SERVER, typename ARGS>
static inline void call_member(Meta::Empty &, SERVER &server, ARGS &args,
static inline RET_TYPE call_member(SERVER &server, ARGS &args,
void (SERVER::*func)(typename Type_at<ARGS, 0>::Type,
typename Type_at<ARGS, 1>::Type,
typename Type_at<ARGS, 2>::Type,
@ -593,7 +589,7 @@ namespace Genode {
typename Type_at<ARGS, 5>::Type,
typename Type_at<ARGS, 6>::Type))
{ (server.*func)(args.get(), args._2.get(), args._2._2.get(), args._2._2._2.get(),
args._2._2._2._2.get(), args._2._2._2._2._2.get(), args._2._2._2._2._2._2.get()); }
args._2._2._2._2.get(), args._2._2._2._2._2.get(), args._2._2._2._2._2._2.get()); return Empty(); }
/********************