/* * \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 #include namespace Genode { class Signal_rpc_dispatcher_base; template class Signal_rpc_functor; template class Signal_rpc_member; template Signal_rpc_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 { 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_cap; protected: Signal_rpc_dispatcher_base() : _proxy(*this) { } Capability 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(); sig_rec.dissolve(this); } public: /** * Interface of Signal_dispatcher_base */ void dispatch(unsigned num) { proxy_cap().call(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 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 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 Genode::Signal_rpc_functor Genode::signal_rpc_functor(FUNCTOR &func) { return Signal_rpc_functor(func); } #endif /* _INCLUDE__OS__SIGNAL_RPC_DISPATCHER_H_ */