FASSWG msg actions

= msg_actions PROPOSAL =

Problem
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.

Approach
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 &quot;normal&quot; class methods or functions as action to be executed on message won't work, because &quot;normal&quot; methods don't take.
 * Define a combined converter + &quot;normal&quot; method: Input is, output is void, but in between,   gets 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  of actions to be taken upon a specific key

Implementation so far
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
 * the  magic that GR already uses when doing   gets used, so (hopefully) no new dependencies or boost strangenesses.
 * the  constructor now sets up a message port to which one can send such pairs, and registers   as handler

Use Cases

 * Intrinsic:  has a non-thread-safe   method. It wants to keep that private and expose a message action. It does

boost::function action = boost::bind(&amp;repeat_impl::set_interpolation, this, _1);@ register_msg_action(pmt::mp(&quot;interpolation&quot;), pmt::to_long, action);
 * Extrinsic: User/GRC knows there's a  method, but   doesn't offer a message passing interface. Instead of despairing, we now can do

boost::function action = boost::bind(&amp;repeat_impl::set_interpolation, this, _1); multiply_const_0-&gt;register_msg_action(pmt::mp(&quot;factor&quot;), pmt::to_float, action); and send pairs (key, value) to the  msg port of the respective block

Discussion

 * How to do getters?
 * Should GR have one central settings &quot;bus&quot;, 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 &quot;Variable&quot; GRC blocks are aware of this


 * All blocks &quot;observing&quot; variable get their &quot;actions&quot; 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.