genode/repos/os/include/os/signal_rpc_dispatcher.h

186 lines
4.7 KiB
C++

/*
* \brief Utility for dispatching signals via an RPC entrypoint **
* \author Norman Feske
* \date 2013-09-07
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__OS__SIGNAL_RPC_DISPATCHER_H_
#define _INCLUDE__OS__SIGNAL_RPC_DISPATCHER_H_
#include <base/rpc_server.h>
#include <base/signal.h>
namespace Genode {
class Signal_rpc_dispatcher_base;
template <typename> class Signal_rpc_functor;
template <typename, typename> class Signal_rpc_member;
template <typename FUNCTOR>
Signal_rpc_functor<FUNCTOR> signal_rpc_functor(FUNCTOR &);
}
struct Genode::Signal_rpc_dispatcher_base : Genode::Signal_dispatcher_base
{
private:
struct Proxy
{
GENODE_RPC(Rpc_handle_signal, void, handle_signal, unsigned);
GENODE_RPC_INTERFACE(Rpc_handle_signal);
};
struct Proxy_component : Genode::Rpc_object<Proxy, Proxy_component>
{
Genode::Signal_rpc_dispatcher_base &_dispatcher;
Proxy_component(Signal_rpc_dispatcher_base &dispatcher)
: _dispatcher(dispatcher) { }
void handle_signal(unsigned num)
{
_dispatcher.dispatch_at_entrypoint(num);
}
};
Proxy_component _proxy;
Capability<Proxy> _proxy_cap;
protected:
Signal_rpc_dispatcher_base() : _proxy(*this) { }
Capability<Proxy> proxy_cap() { return _proxy_cap; }
public:
/**
* Associate signal dispatcher with entrypoint
*/
Signal_context_capability manage(Signal_receiver &sig_rec, Rpc_entrypoint &ep)
{
_proxy_cap = ep.manage(&_proxy);
return sig_rec.manage(this);
}
/**
* Disassociate signal dispatcher from entrypoint
*/
void dissolve(Signal_receiver &sig_rec, Rpc_entrypoint &ep)
{
ep.dissolve(&_proxy);
_proxy_cap = Capability<Proxy>();
sig_rec.dissolve(this);
}
public:
/**
* Interface of Signal_dispatcher_base
*/
void dispatch(unsigned num) {
proxy_cap().call<Proxy::Rpc_handle_signal>(num); }
/**
* To be implemented by the derived class
*/
virtual void dispatch_at_entrypoint(unsigned num) = 0;
};
/**
* Signal dispatcher that executes the signal handling code in the context
* of an RPC entrypoint
*
* The 'Signal_rpc_dispatcher' provides an easy way for a server to serialize
* the handling of signals with incoming RPC requests. Incoming signals are
* delegated to the RPC entrypoint via a local RPC call. The signal handling
* code is then executed in the context of the RPC entrypoint.
*/
template <typename FUNCTOR>
struct Genode::Signal_rpc_functor : Genode::Signal_rpc_dispatcher_base
{
FUNCTOR &functor;
/**
* Constructor
*
* \param func functor taking containing the signal-handling code
*
* The functor 'func' has the signature 'void func(unsigned num)'
* whereas 'num' is the number of signals received at once.
*/
Signal_rpc_functor(FUNCTOR &functor) : functor(functor) { }
/**
* Interface of Signal_rpc_dispatcher_base
*/
void dispatch_at_entrypoint(unsigned num) { functor(num); }
};
namespace Server{
class Entrypoint;
}
/**
* Signal dispatcher for directing signals via RPC to member function
*
* This utility associates member functions with signals. It is intended to
* be used as a member variable of the class that handles incoming signals
* of a certain type. The constructor takes a pointer-to-member to the
* signal handling function as argument. If a signal is received at the
* common signal reception code, this function will be invoked by calling
* 'Signal_dispatcher_base::dispatch'.
*
* \param T type of signal-handling class
* \param EP type of entrypoint handling signal RPC
*/
template <typename T, typename EP = Server::Entrypoint>
struct Genode::Signal_rpc_member : Genode::Signal_rpc_dispatcher_base,
Genode::Signal_context_capability
{
EP &ep;
T &obj;
void (T::*member) (unsigned);
/**
* Constructor
*
* \param ep entrypoint managing this signal RPC
* \param obj,member object and member function to call when
* the signal occurs
*/
Signal_rpc_member(EP &ep, T &obj, void (T::*member)(unsigned))
: Signal_context_capability(ep.manage(*this)),
ep(ep), obj(obj), member(member) { }
~Signal_rpc_member() { ep.dissolve(*this); }
/**
* Interface of Signal_rpc_dispatcher_base
*/
void dispatch_at_entrypoint(unsigned num) { (obj.*member)(num); }
};
/**
* Convenience utility for creating 'Signal_rpc_dispatcher' objects
*/
template <typename FUNCTOR>
Genode::Signal_rpc_functor<FUNCTOR> Genode::signal_rpc_functor(FUNCTOR &func)
{
return Signal_rpc_functor<FUNCTOR>(func);
}
#endif /* _INCLUDE__OS__SIGNAL_RPC_DISPATCHER_H_ */