Event dispatcher, hooks and Interceptor pattern for C++?

L

Lothar Behrens

Are there any documents available about the interceptor pattern?

I have a class that registers an event handler to be called on a given
event. The interceptor pattern then should be used to add restrictions
or other things to the function.

I could implement that in my dispatcher class (like an event
dispatcher pattern), but I think there are patterns also usable for
this issue in C++.

I have cases where I register event handlers per class and others per
instance (by adding the pointer to the event name). Thus when I have
an event handler per instance, but a interceptor
per class I have to strip the pointer from the event name (after
resolving it from the number) to locate the handler correctly.

Any help out there?

Thanks

Lothar
 
P

Pavel

Lothar said:
Are there any documents available about the interceptor pattern?

I have a class that registers an event handler to be called on a given
event. The interceptor pattern then should be used to add restrictions
or other things to the function.

I could implement that in my dispatcher class (like an event
dispatcher pattern), but I think there are patterns also usable for
this issue in C++.

I have cases where I register event handlers per class and others per
instance (by adding the pointer to the event name). Thus when I have
an event handler per instance, but a interceptor
per class I have to strip the pointer from the event name (after
resolving it from the number) to locate the handler correctly.

Any help out there?

Thanks

Lothar
RTTI in C++ is not sophisticated enough to get you a static function if
you have a typeid or another "runtime id" of the event class.

You could probably construct your own metadata ("Runtime Class") so you
could refer to an instance of "RunTime class" from a virtual method of
your event or from "dispatchEvent" or similar method of your event
dispatcher, based on the result of some virtual method of the event
returning some form of its class id (maybe even typeid).

Alternatively, with somewhat lesser flexibility, you could put your
intercepting logic into the method of the event itself, something along
these lines:

class Event;
class EventHandler {
public:
virtual void handle(Event *)=0;
};

class Event {
public:
void process() {
if (!intercept())
handler_.handle(this);
} // I assume that's what you meant by "adding pointer to the event name"
virtual bool intercept(Event *) = 0;
private:
EventHandler handler_;
};

class ConcreteEvent : public Event {
public:
bool intercept() {
// one algorithm per event class here
// so no need to register
}
};

I am not sure I captured your problem fully; it would help if you posted
some source code to illustrate the issue.

-Pavel
 
L

Lothar Behrens

RTTI in C++ is not sophisticated enough to get you a static function if
you have a typeid or another "runtime id" of the event class.

You could probably construct your own metadata ("Runtime Class") so you
could refer to an instance of "RunTime class" from a virtual method of
your event or from "dispatchEvent" or similar method of your event
dispatcher, based on the result of some virtual method of the event
returning some form of its class id (maybe even typeid).

Alternatively, with somewhat lesser flexibility, you could put your
intercepting logic into the method of the event itself, something along
these lines:

class Event;
class EventHandler {
public:
        virtual void handle(Event *)=0;

};

class Event {
public:
        void process() {
                if (!intercept())
                        handler_.handle(this);
        } // I assume that's what you meant by "adding pointer to the event name"
        virtual bool intercept(Event *) = 0;
private:
        EventHandler handler_;

};

class ConcreteEvent : public Event {
public:
        bool intercept() {
// one algorithm per event class here
// so no need to register
        }

};

I am not sure I captured your problem fully; it would help if you posted
some source code to illustrate the issue.

-Pavel

The C++ language may not have the same capabilities as java, so I need
a dispatcher where I register my callbacks to names or ID's.
The event handler pattern is not the problem, as I use it since some
years.

The interceptor as I do understad, is a pre and post condition I could
activate on demand to change the plain behavior for sample to
add permission handling.

My problem is if this interceptor pattern is also usable if I have a
class (that is a database form) and I have different form instances
and thus different interceptors are required to add logic depending on
the particular form. Thus I may have more than one interceptor per
form. The form it self is a dynamic implementation to be used for
different data to be shown, thus there may also different
interceptors.

My main issue is about saving code. Another function I previously have
implemented is inside of the handlers. I don't like to keep adding
any more if I can do the same with interceptors. (application hooks
will become interceptors)

Lothar
 
P

Pavel

Lothar said:
The C++ language may not have the same capabilities as java, so I need
a dispatcher where I register my callbacks to names or ID's.
The event handler pattern is not the problem, as I use it since some
years.

The interceptor as I do understad, is a pre and post condition I could
activate on demand to change the plain behavior for sample to
add permission handling.

My problem is if this interceptor pattern is also usable if I have a
class (that is a database form) and I have different form instances
and thus different interceptors are required to add logic depending on
the particular form. Thus I may have more than one interceptor per
form. The form it self is a dynamic implementation to be used for
different data to be shown, thus there may also different
interceptors.

My main issue is about saving code. Another function I previously have
implemented is inside of the handlers. I don't like to keep adding
any more if I can do the same with interceptors. (application hooks
will become interceptors)

Lothar
I guess I am slightly confused then. I thought you wanted one
interceptor per class (even though I could not clearly understand -- per
event class, event source class or event handler class; in my example, I
assumed you wanted one interceptor per event class).

From your last post, however, I cannot see a difference between event
handler and event interceptor other than that you want some interceptors
to be called before and some after event handlers for same event. I
think you can achieve this without introducing new concept of an
Interceptor, simply with event handlers you already have. You could
register event handlers in a priority queue (with the priorities like
enum { PRE_INTERCEPTOR_PTY, REGULAR_HANDLER_PTY, POST_INTERCEPTOR_PTY }
) or two or three separate lists (two or three depending on whether you
want both "pre-" and "post-" interceptors). Also, if you want to be able
to stop event handling in an interceptor (to "veto" an event in terms of
Java or Interceptor pattern), you will need a boolean "processed"
attribute in events or alternatively you could make "handleEvent" return
bool.

If you require even more complex interactions between event handlers
(for example, you want to be able to skip some handlers but still
execute the last "logging" interceptor), you may need to add more
complex information to an event.

-Pavel
 
L

Lothar Behrens

I guess I am slightly confused then. I thought you wanted one
interceptor per class (even though I could not clearly understand -- per
event class, event source class or event handler class; in my example, I
assumed you wanted one interceptor per event class).

First of all, I work on a fully dynamic application that is used to
prototype
database applications.

Say, I have one class - the form - that is responsible to display data
on the
screen and provides some CRUD functions. Then I would like to
'validate' the
entered data, but not with hard coded logic, but rather with a hooked
function.

Until now each function (OnFirst, OnPrevious, OnNext, ...) calls the
validator
indirectly by configuration. So then I speak about hooks I have
inserted in each
of these functions.

A validator it self is a dynamic function that executes an activity I
model in UML.
Each form may have one validator - for now. The dynamic database form
that shows
SQL data, is driven by a simple SQL query, thus the form
(implementation) cannot have
only one hook.

My question goes in the direction to avoid adding more hooks like the
one for validation
purposes. That way I would save adding more an more across my code.
The code is highly
dynamic, thus I need another solution, but I think it is a mixture of
several patterns.

The above event handlers - and indeed simple methods - are candidates
for the interceptor
pattern. The simple solution would be moving the hook to outside of
these functions and
execute the validator before the OnXXX handler.

But the fact that these event handlers are called from my event
dispatcher class, I thought
to move the interceptor functionality INTO my dispatcher
implementation.

If in the dispatcher, I come to the result that I must be able to
support more than one pre-
and post interceptor.

To give you right, that one interceptor per class is meant. I could
have one interceptor that
only validates that all NOT NULL database columns have to be filled
may valid for all
of my instances of the dynamic form class.

This interceptor may be simple and enough for a trivial database form.
But I have a dynamic
implementation, thus one class serves as many forms as you like. You
will truly have a need
for more than one interceptor. This is the nature of the dynamic form.

So in my implementation, speaking only about one event handler
function (OnNext for sample),
I would have the following pseudo code:

void MyDynamicForm::Initialize(char* SQL) {

long MyOnNextID;
char* eventName[100] = "";
sprintf(eventName, "%pOnNext", (void*)this); // Create an event per
instance !!

MyEventManager->registerEvent(eventName, &MyOnNextID); // Register
and get an identifier

// Tell the dispatcher what to call on event eventName (eventName =
0x12345678OnNext)
MyDispatcher->setEventHandler(eventName, this,
(MyEvHandlerFunction*) MyMainForm::OnNext);

// Create a button and connect the ID of the event to the button.
MyButton* bOnNext = new MyButton(MyOnNextID, "&Next");

// Connect the GUI element to a 'GUI' event handler. It translates
all GUI events to events of my event system.
bOnNext->Connect(GUI_ON_BUTTON_CLICK, (GUIEvHandlerFunction*)
MyMainForm::OnDispatch);
}

void MyDynamicForm::OnNext(MyBaseClass_Interface* unknown) {
// Simply save edited data and move to next entry. No validation or
any business logic.
}

Now the form is initialized, a click on the 'Next' button will fire an
event and it gets routed
over the OnDispatch handler to the dispatcher that looks for the right
handler and then the dispatcher
forwards the event to MyDynamicForm::OnNext(MyBaseClass_Interface*
unknown)

NOTE: This is a handler per instance, as the event name contains the
pointer to the instance as a string.

I need this because I have one dispatcher (singleton), but may have
several instances each having this button.
(How should I else route the event to the correct instance?)

Now as the basic structure is explained how I do stuff, I'll begin
with the interceptor.
My first approach was this one (the dynamic validator approach with an
activity):

void MyDynamicForm::OnNext(MyBaseClass_Interface* unknown) {

// Say Formularname is 'Customers' in this instance.

if (haveValidator(Formularname)) {
if (!executeValidator(Formularname)) {
// Show some error message
return;
}
}

// Simply save edited data and move to next entry. No validation or
any business logic.
}

Dit you spot the need for several different interceptors (it's
dynamic)?

It is a little bit complicated, but it works.

Now I would like to add more interceptors but don't like to add the
interceptor code in each
of my handlers (OnNext).

Did you spot the dispatcher class I used?

I think that this is the caller and OnNext is the called. I would like
to put the interceptor
logic into the dispatcher that could look if there is a registered
interceptor for the current
event to dispatch.


MyDispatcher::dispatch(eventID, MyBaseClass_Interface* unknown) {

if (haveInterceptor(eventID)) {
if (!executeInterceptor(eventID)) {
// No error reporting here. The interceptor may do this
return;
}
}

MyEventhandler* evh = lookup(eventID);
evh->call(unknown);

// Post omitted here :)
}

Now I would be able to dynamically hook an interceptor into any event
handler. The only issue
now is the point that I must detect interceptors that are registered
per class and not per instance.

This means, that I register an event handler name without the pointer
to a specific instance.

The problem is not the lookup of the class that actually handles the
event. I could filter out event
handlers with a pointer to the instance by searching for the pointer
(string) of the actual instance
looked up.

I think there may be a problem when I have one interceptor per class
and several per instance. But it
may be simple to solve the issue. Per class interceptors should do
generic stuff that may be checking
for email field having correct email address or may not be empty if
the database column is not nullable.

I could argue that these interceptors are hard coded ones and hooked
to the OnNext function for all forms
and thus per class. These functions may also faster and may be
executed beforehand of more complicated
interceptors.

It seems that the problem is solved. I think I asked about any pattern
that may be defined and I am using
it without knowledge. It is also a really complicated issue :)
 From your last post, however, I cannot see a difference between event
handler and event interceptor other than that you want some interceptors
to be called before and some after event handlers for same event. I
think you can achieve this without introducing new concept of an
Interceptor, simply with event  handlers you already have. You could
register event handlers in a priority queue (with the priorities like
enum { PRE_INTERCEPTOR_PTY, REGULAR_HANDLER_PTY, POST_INTERCEPTOR_PTY }
) or two or three separate lists (two or three depending on whether you
want both "pre-" and "post-" interceptors). Also, if you want to be able
to stop event handling in an interceptor (to "veto" an event in terms of
Java or Interceptor pattern), you will need a boolean "processed"
attribute in events or alternatively you could make "handleEvent" return
bool.

That or similar thought I have :)

I'll keep the above text as I have overseen your suggestion.

But it is not only plain interceptor, as of the dynamic nature of my
application - events back or forth :)

The complicated thing is that the interceptors have a scope to a
generic or per instance event handler and
not to the dispatcher.

The plain interceptor in java has it's scope to the class that it
intercepts, I think. And in my requirement
are much more aspects.

So the main questions are:

Is there a pattern that becomes close to my problem?

Or are there any (close to this) solutions using different patterns?

Or do I indeed using THE patterns that match best?
If you require even more complex interactions between event handlers
(for example, you want to be able to skip some handlers but still
execute the last "logging" interceptor), you may need to add more
complex information to an event.

Yes, so much to think about. And that's why I ask for patterns. I
think I use more than I know about :)

The problem is the nature of dynamic applications or prototyping
software. You can't
capture all the possible things one would do with it.

And that's why I ask. One may stumbled over and has got a solution and
could hint. (logging)

There may be others too (transaction rollback / commit). But I think
this will become an issue of the
designer do do correctly.

Also a big issue is the extensibility of my application with plugins.
A plugin may add new features,
or may add interceptors to be used for other components.

And at the end I like to find a way to model these things in UML
(activity diagrams are currently
used to model validators).

Doing more complex things may lead into a workflow engine - another
issue I partly have done (activity).

I hope the text was not too long :)

Lothar
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,132
Latest member
TeresaWcq1
Top