Redesigning the event_manager class

Following a discussion on the maintainers mailing list that was partly about improving the implementation of the event_manager class in Octave, I’ve been thinking about how to allow a single message (for example, “directory_changed”) to be associated with more than one action and also how to simplify subscribing to events.

One solution would be to use Qt signals and slots directly in Octave, but I would prefer to avoid that because I’d like to allow non-Qt projects to also subscribe to messages emitted by the Octave interpreter.

Another solution I came up with uses templates and an enumerated list of message IDs. A simple prototype is here: message-queue.cc (5.7 KB) . This approach has some advantages of type safety (the type signature of action functions must match the type declared for the message ID) but requires some work to add a new message (you must add a new global enum value and declare the type signature used by the associated action function).

Another possibility is to have each action function declared as one of

void FCN (const octave_value_list& args);
void FCN (interpreter& interp, const octave_value_list& args);

similar to the DEFUN or DEFMETHOD functions in the interpreter, except that these action function would not return values. If all action functions are required to be of a pre-defined set of types, then we can dynamically add messages instead of having a fixed set of message IDs, but we give up compile time checking to ensure that an action function matches the type signature of the corresponding message.

Edit: What I mean by “but we give up compile time checking to ensure that an action function matches the type signature of the corresponding message” isn’t that we can’t check that the matches one of the signatures void(const octave_value_list&) or void(interpreter&, const octave_value_list&) but that when we emit a message, we can’t check at compile time that the number and types of the variables in the octave_value_list argument match what the action function expects.

A prototype implementation of this idea is here: ovl-message-queue.cc (4.9 KB) .

Thoughts? At the moment I’m leaning toward the latter solution because of the additional flexibility it offers even though it may require storing C++ values in octave_value_list objects for the calls to the action functions and then extracting values inside the action functions. At least this is a pattern that anyone who writes Octave extensions should be familiar with.

Thinking about this a little more, it would probably make sense to just have the functions be of exactly the same form as the DEFUN and DEFMETHOD functions so that we could handle the dialog functions that block the interpreter and do return values.

An argument against what I wrote in the previous comment is that if the action functions can return values and multiple action functions can be attached to a single message, then its not clear how return values should be handled. How does Octave distinguish messages that will block and return values vs. ones that will just invoke a (possible list of) actions at some later time, possibly across threads?