FASSWG msg actions
Millions of setters in GNU Radio. Some safe to call from another thread whilst general_work is running, others not. No unified scheme of communicating settings.
Harnessing the power of message passing, and using a bit of old school boost magic to put functions into STL containers, so that they can be automagically called.
Theory of operation:
- Registering a "normal" class methods or functions as action to be executed on message won't work, because "normal" methods don't take
- Define a combined converter + "normal" method: Input is
pmt_t, output is void, but in between,
pmt_tgets converted to the native argument type of the method
- Define a converter function; in most case, the PMT standard converters do, e.g.
- Find a way to do something like a lambda without breaking with old Boost / C++-pre-0x
- Registry can then be of function(al)s that are
- Registry has
std::vectorof actions to be taken upon a specific key
basic_block::register_msg_action(key,conv,action) method (or rather four methods, including three convenience wrappers):
registers an action by generating a function chain functor, and putting that in a std::vector in a std::map.
triggers all actions registered for a single key
takes in pairs like
boost::bindmagic that GR already uses when doing
register_msg_handlergets used, so (hopefully) no new dependencies or boost strangenesses.
basic_blockconstructor now sets up a message port to which one can send such pairs, and registers
gr::blocks::repeat_implhas a non-thread-safe
set_interpolation(int)method. It wants to keep that private and expose a message action. It does
boost::function action = boost::bind(&repeat_impl::set_interpolation, this, _1);@ register_msg_action(pmt::mp("interpolation"), pmt::to_long, action);
- Extrinsic: User/GRC knows there's a
multiply_constdoesn't offer a message passing interface. Instead of despairing, we now can do
boost::function action = boost::bind(&repeat_impl::set_interpolation, this, _1); multiply_const_0->register_msg_action(pmt::mp("factor"), pmt::to_float, action);and send pairs (key, value) to the
pmt::mp("actions")msg port of the respective block
- How to do getters?
- Should GR have one central settings "bus", to which blocks' setters automatically are subscribed?
Yet to do
- drawing pretty pictures and expanding docs beyond the doxygen method docs
- block_gateway to enable python methods to be registered. Should be relatively simple, if it weren't for swig.
- replacing GRC's callback mechanism by something that registers a python function as action handler
- Will require that "Variable" GRC blocks are aware of this
- All blocks "observing" variable get their "actions" port subscribed to the variable's message_publisher
As you can see, not nearly complete, but already useful. I'm not quite sure the naming and architecture take things in the right direction, so I RFC before I PR.