genode/repos/base/include/base/rpc_client.h

205 lines
6.4 KiB
C
Raw Normal View History

2011-12-22 16:19:25 +01:00
/*
* \brief Support for performing RPC calls
* \author Norman Feske
* \date 2011-04-06
*/
/*
* Copyright (C) 2011-2017 Genode Labs GmbH
2011-12-22 16:19:25 +01:00
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
2011-12-22 16:19:25 +01:00
*/
#ifndef _INCLUDE__BASE__RPC_CLIENT_H_
#define _INCLUDE__BASE__RPC_CLIENT_H_
#include <base/ipc.h>
2013-08-13 16:15:52 +02:00
#include <base/trace/events.h>
2011-12-22 16:19:25 +01:00
namespace Genode {
template <typename> class Rpc_client;
2011-12-22 16:19:25 +01:00
/**
* Count capabilities of a RPC_FUNCTION which are out parameters.
*/
template <typename T> struct Cap_para_out { enum { Value = 0 }; };
template <typename T> struct Cap_para_out<Capability<T> *> { enum { Value = 1 }; };
template <typename T> struct Cap_para_out<Capability<T> &> { enum { Value = 1 }; };
template <> struct Cap_para_out<Native_capability *> { enum { Value = 1 }; };
template <> struct Cap_para_out<Native_capability &> { enum { Value = 1 }; };
template <typename T> struct Cap_return { enum { Value = 0 }; };
template <typename T> struct Cap_return<Capability<T> > { enum { Value = 1 }; };
template <typename T> struct Cap_return<Capability<T> *> { enum { Value = 1 }; };
template <typename T> struct Cap_return<Capability<T> &> { enum { Value = 1 }; };
template <> struct Cap_return<Native_capability> { enum { Value = 1 }; };
template <> struct Cap_return<Native_capability *> { enum { Value = 1 }; };
template <> struct Cap_return<Native_capability &> { enum { Value = 1 }; };
template <typename ARGS>
struct Rpc_caps_out {
enum { Value = Cap_para_out<typename ARGS::Head>::Value
+ Rpc_caps_out<typename ARGS::Tail>::Value }; };
template <>
struct Rpc_caps_out<Meta::Empty> { enum { Value = 0 }; };
template <typename RPC_FUNCTION>
struct Rpc_function_caps_out {
enum { Value = Rpc_caps_out<typename RPC_FUNCTION::Server_args>::Value +
Cap_return <typename RPC_FUNCTION::Ret_type>::Value}; };
2011-12-22 16:19:25 +01:00
/***************************************************
2011-12-22 16:19:25 +01:00
** Implementation of 'Capability:call' functions **
***************************************************/
2011-12-22 16:19:25 +01:00
template <typename RPC_INTERFACE>
template <typename ATL>
void Capability<RPC_INTERFACE>::
_marshal_args(Msgbuf_base &msg, ATL &args) const
2011-12-22 16:19:25 +01:00
{
if (Trait::Rpc_direction<typename ATL::Head>::Type::IN)
msg.insert(args.get());
2011-12-22 16:19:25 +01:00
_marshal_args(msg, args._2);
2011-12-22 16:19:25 +01:00
}
template <typename RPC_INTERFACE>
template <typename T>
void Capability<RPC_INTERFACE>::
_unmarshal_result(Ipc_unmarshaller &unmarshaller, T &arg,
Meta::Overload_selector<Rpc_arg_out>) const
2011-12-22 16:19:25 +01:00
{
unmarshaller.extract(arg);
2011-12-22 16:19:25 +01:00
}
template <typename RPC_INTERFACE>
template <typename T>
void Capability<RPC_INTERFACE>::
_unmarshal_result(Ipc_unmarshaller &unmarshaller, T &arg,
Meta::Overload_selector<Rpc_arg_inout>) const
2011-12-22 16:19:25 +01:00
{
_unmarshal_result(unmarshaller, arg, Meta::Overload_selector<Rpc_arg_out>());
2011-12-22 16:19:25 +01:00
}
template <typename RPC_INTERFACE>
template <typename ATL>
void Capability<RPC_INTERFACE>::
_unmarshal_results(Ipc_unmarshaller &unmarshaller, ATL &args) const
2011-12-22 16:19:25 +01:00
{
/*
* Unmarshal current argument. The overload of
* '_unmarshal_result' is selected depending on the RPC
* direction.
*/
typedef typename Trait::Rpc_direction<typename ATL::Head>::Type Rpc_dir;
_unmarshal_result(unmarshaller, args.get(), Meta::Overload_selector<Rpc_dir>());
2011-12-22 16:19:25 +01:00
/* unmarshal remaining arguments */
_unmarshal_results(unmarshaller, args._2);
2011-12-22 16:19:25 +01:00
}
template <typename RPC_INTERFACE>
template <typename IF>
typename IF::Ret_type Capability<RPC_INTERFACE>::
_call(typename IF::Client_args &args) const
2011-12-22 16:19:25 +01:00
{
/**
* Message buffer for RPC message
*
* The message buffer gets automatically dimensioned according to the
* specified 'IF' RPC function.
*/
enum { PROTOCOL_OVERHEAD = 4*sizeof(long),
CALL_MSG_SIZE = Rpc_function_msg_size<IF, RPC_CALL>::Value,
REPLY_MSG_SIZE = Rpc_function_msg_size<IF, RPC_REPLY>::Value,
RECEIVE_CAPS = Rpc_function_caps_out<IF>::Value };
2011-12-22 16:19:25 +01:00
Msgbuf<CALL_MSG_SIZE + PROTOCOL_OVERHEAD> call_buf;
Msgbuf<REPLY_MSG_SIZE + PROTOCOL_OVERHEAD> reply_buf;
/* determine opcode of RPC function */
typedef typename RPC_INTERFACE::Rpc_functions Rpc_functions;
Rpc_opcode opcode(static_cast<int>(Meta::Index_of<Rpc_functions, IF>::Value));
2011-12-22 16:19:25 +01:00
/* marshal opcode and RPC input arguments */
call_buf.insert(opcode);
_marshal_args(call_buf, args);
2011-12-22 16:19:25 +01:00
2013-08-13 16:15:52 +02:00
{
Trace::Rpc_call trace_event(IF::name(), call_buf);
}
2011-12-22 16:19:25 +01:00
/* perform RPC, unmarshal return value */
Rpc_exception_code const exception_code =
ipc_call(*this, call_buf, reply_buf, RECEIVE_CAPS);
if (exception_code.value == Rpc_exception_code::INVALID_OBJECT)
throw Ipc_error();
Ipc_unmarshaller unmarshaller(reply_buf);
2011-12-22 16:19:25 +01:00
2013-08-13 16:15:52 +02:00
{
Trace::Rpc_returned trace_event(IF::name(), reply_buf);
}
2011-12-22 16:19:25 +01:00
/* unmarshal RPC output arguments */
_unmarshal_results(unmarshaller, args);
2011-12-22 16:19:25 +01:00
/* reflect callee-side exception at the caller */
_check_for_exceptions(exception_code,
2011-12-22 16:19:25 +01:00
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);
2011-12-22 16:19:25 +01:00
}
}
/**
* RPC client
*
* This class template is the base class of the client-side implementation
* of the specified 'RPC_INTERFACE'. Usually, it inherits the pure virtual
* functions declared in 'RPC_INTERFACE' and has the built-in facility to
* perform RPC calls to this particular interface. Hence, the client-side
* implementation of each pure virtual interface function comes down to a
* simple wrapper in the line of 'return call<Rpc_function>(arguments...)'.
*/
template <typename RPC_INTERFACE>
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
class Genode::Rpc_client : public RPC_INTERFACE
{
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
private:
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
Capability<RPC_INTERFACE> _cap;
public:
typedef RPC_INTERFACE Rpc_interface;
Rpc_client(Capability<RPC_INTERFACE> const &cap) : _cap(cap) { }
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
template <typename IF, typename... ARGS>
typename IF::Ret_type call(ARGS &&...args)
{
return _cap.template call<IF>(args...);
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
}
template <typename IF, typename... ARGS>
typename IF::Ret_type call(ARGS &&...args) const
{
return _cap.template call<IF>(args...);
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
}
Capability<RPC_INTERFACE> rpc_cap() const { return _cap; }
};
2011-12-22 16:19:25 +01:00
#endif /* _INCLUDE__BASE__RPC_CLIENT_H_ */