Runtime event handler in cpp? - c++

Working on a cpp project, where I need something like runtime event handler. My primary goal is to keep a track of various events that takes place in a sample program and based on the events specific handlers are triggered.
These event triggering handlers/functions are not contributing anything to the global objective of the sample program, but are just keeping track over various events in the cpp sample program.
My question is it prossible to create soemthing like custom eventhandlers in cpp?
If yes, is there any tutorial for creating such custom eventhandler?
eg:
Event are like failed to enter while loop. successfully entered while loop, created object, deleted object, changed global variable etc.

The simplest form of event handler is a registered callback function pointer:
enum Events {
FailedEnteringWhileLoop ,
SuccessfullyEnteredWhileLoop ,
};
typedef void(EventHandler*)(Events);
void MyEventHandler(Events ev) {
switch(ev) {
case FailedEnteringWhileLoop:
// Do something
break;
case SuccessfullyEnteredWhileLoop:
// Do something
break;
}
}
EventHandler evh = MyEventHandler;
bool whileLoopEntered = false;
while(condition) {
if(!whileLoopEntered) {
whileLoopEntered = true;
(*evh)(SuccessfullyEnteredWhileLoop);
}
}
if(!whileLoopEntered) {
(*evh)(FailedEnteringWhileLoop);
}

I am looking for events like failed to enter while loop. successfully
entered while loop, created object, deleted object, changed global
variable etc.
The C++ language itself does not track these kinds of things as "events". Generally speaking it doesn't provide hooks into any of the various fundamental activities that happen across code.
So to do what you're asking for requires building an infrastructure yourself and working it into your code in various ways. (Or finding someone else who has done the same sort of work already and made it available. Although you still would have to integrate it into your code.)
To give some idea of what might have to be done:
For creating and deleting objects you can override the new and delete operators. But that doesn't cover stack/local/etc objects. Otherwise you could wedge something the constructors and destructors of every class you want to track, or even have all of them derive from a common base class which encapsulates the tracking.
For changes to a variable, you would have to wrap that variable in a container which only exposes the ability to change it through member functions. Then those could be coded to raise events.
For entering loops... You're out of luck because a loop isn't an entity that can be extended or hooked. You literally have to put some kind of call at every loop you want to track.
As for the rest of the infrastructure, you would probably end up doing something like having all of those various "events" call to some kind of global logging object. If you need different things catch different events over the course of a program, then you might also need to build a way of registering and de-registering listeners (the listeners themselves being based on an interface to derive from or std::function or whatever suits your use case).
But in the end since there isn't an out-of-the-box way provided by the language, you might want to re-consider what you really want and what you hope to achieve with it. In fact you might be better off asking your question in terms how to accomplish the end goal you wanted this for rather than how to do this "event" system.

Related

Disadvantages of using a function pointer as an UI-Button callback

I am currently creating my own GUI-Library based on SFML.
At the moment i am working on a Button. So when creating a button you also have to specify a callback which is a function, executed on the button click.
Now, I'm answering me what the disadvantages are of using just a pointer to a function as a button-callback, because I don't know any popular GUI-Library doing it so simply, too.
If the callback function is a long process, I would execute it in a new thread, but i'm not sure about that in the moment.
So, what would be reasons, not to use such simple solution and especially, what would be a better way?
It's a tricky problem!
Function pointers are simple to implement on the sender side, but they are difficult to use on the receiver side because they they don't have any context.
One issue is that a function pointer cannot point to a member function. That's why you often see (C-style) frameworks pass an arbitrary void *userData to their callbacks, so you can cast your this pointer and retrieve it in that way. This still needs you to write a static wrapper function to cast the pointer back and call the member function.
A more modern solution would be to use std::function. This can contain a regular function pointer, a member function pointer, but also a lambda or a functor.
However, when you add context like this (or in some other way), you quickly run into difficulties with lifetimes. When the receiving class is destroyed before the sender, what is supposed to happen? If you don't do anything, this situation will result in undefined behaviour. A solution is to track on the receiver side to which events the receiver is subscribed, and unbind them before the receiver is destroyed. And this needs to be done in both directions: when the sender is destroyed, it also needs to notify the receiver that it should forget about the sender, otherwise the receiver would later try to unbind an event that no longer exists.
And I haven't even begun to think about multithreading yet...
There are libraries that solve these problems in various ways, for example eventpp (just found through a web search, this is not an endorsement).
Another one to mention would be the Qt toolkit, which went so far as to write their own small signals and slots extension to the C++ language (implemented as a code generator and a pile of macros) to solve this problem in a very ergonomical way.
what the disadvantages are of using just a pointer to a function as a button-callback
Passing some context argument to that function would come handy.
I mean, the UI may have a lot of buttons performing the same action on various objects. Think maybe of "send message" button next to each nick in a friend list.
So you may want your buttom to pass some context arguments to the call.
But since we're talking C++, this'd better be abstracted as
struct IButtonAction
{
virtual void OnAttached() = 0;
virtual void OnDetached() = 0;
virtual void OnClick() = 0;
};
And let the client code implement this interface storing whichever Arg1, Arg2, etc in each instance object.
The button class would call OnAttached/OnDetached when it begins/ends using the pointer to an instance of this callback interface. These calls must be paired. Client implementation of these methods may perform lifetime management and synchronization with OnClick, if required.
OnClick method performs the action.
I don't think the button should bother with threads. It's the responsibility of the client code to decide whether to spawn a thread for a lengthy action.

Should I use Qprocess on the stack

is there any draw back of creating QProcess on the stack,
for something trivial like this
void Utils::changeFont()
{
QString command("book");
QStringList arguments({"opensans", "10"});
QProcess fontProcess;
fontProcess.start(command,arguments);
fontProcess.waitForFinished();
}
i have 10 Utils objects created;
Utils a , b , c .....,
the all call the Utils::changeFont() respectively.
would it be good for the process to be on the stack
i am asking because i have not seen it being used like this on any tutorial.
thanks
The issue here is not related to creating QProcess "on the stack". In fact, stack is a misnomer: what you're really asking is "can I create QProcess as a local variable". Yes, you can, of course!
But such a QProcess is useless, because you're not supposed to use the waitFor methods - not ever. They are a horrible API. Don't use them: instead, write asynchronous code - i.e. react to the signals indicated by the QProcess. In your case, all you need is to delete the object when the process is finished. Thus:
// Not a class!!
namespace Utils {
void changeFont()
{
QString command("book");
QStringList arguments({"opensans", "10"});
auto *fontProcess = new QProcess(context);
QObject::connect(fontProcess,
qOverload<int, QProcess::ExitStatus>(&QProcess::finished),
fontProcess, &QProcess::deleteLater);
fontProcess->start(command,arguments);
}
}
Note that Utils shouldn't be a class - it's a terrible Java-ism. If you want to group utility functions in a namespace, use a namespace! That's what they are for :) The changeFont as presented shouldn't be a method, since it'd just become a static method, and at that point you don't need any state. If you need state, then the class needs to be way more specific than Utils - it may be e.g. a class that adapts QProcess to your particular uses, but it'd need to be very specific, otherwise you end up with deeply coupled spaghetti code.
In C++ there is almost never a reason to have Utils be a class. It's a typical red flag in code reviews. It needs to be a namespace, and if you actually need a class that keeps state, it must be a task-specific class that does one thing and does it well, and has no other functionality.
If you need to e.g. continue whatever work you were in the middle of once the process is finished, you should create a state machine and react to the state transition when the process is finished, and perform subsequent actions there. This way you'll also be explicit about what to do in case of errors. Such issues are plastered over when you write pseudo-synchronous code. If your code has any waitFor calls, it's basically broken - you just don't know it yet. Qt has done everyone a grave disservice for providing those pseudosynchronous methods. All they are good for is freezing the UI. Awful stuff if you care one bit about your user experience.
The example with new QProcess(parent) from the docs also assigns a parent QObject. You will need that (or another ownership strategy) if the process outlives the scope of the QProcess, which the example tacitly assumes.
In your case, you're calling waitForFinished() so it's fine if the QProcess gets deleted at the end of the function. There is no need for it to live longer.
That is ok, actually almost all examples in Qt documentation show creation of the QProcess on the stack.
The only drawback is the creation of the object itself. If you need it "rather often" maybe it would be better to create it once.

(OOP) Events in a main loop, and updating dependencies in constructor

Recently I started a project in hopes to learn OpenGL in C++,and I got stuck on a problem regarding code architecture.
First Question, should I avoid using events in a main loop?
Example:
Event* UpdateEvent = new Event();
int main(){
while(1)
UpdateEvent->Invoke();
}
SomeOtherClass::SomeOtherClass(){
UpdateEvent->Hook(this->DoSomethingAlways);
}
Events from my understanding of C++ code, have a certain amount of penalty in their codes (virtual methods, looping throught events, handling the event stack/array). If i were to implement it in such a way there would definitely be a fair amount of calls on it (Controllers, Coroutines etc.) and this might prove to not be as performant.
Secondly, Should I avoid subscribing to events / update outside variables in constructor?
Or should I instead implement factories? Example:
//Constructor
MyClass::MyClass(){
Dependency::Instance->AddObject(this);
}
Dependency::AddObject(MyClass obj){
InternalList.push(obj);
InternalEvent.Hook(obj->EventHandler);
}
Seen from previous code, I have a habit of subscribing to events in a constructor, and doing other automatic tasks in constructor (Eg. Adding a constructed to some singleton manager). I like doing this because it avoids a need for factories, and creates a little bit more elegant code. But on the other hand, if someone else were to work on this after (Like me in the future) he might not know that certain objects automatically update their dependency objects.

How to write a nested handler for rapidjson deserialization?

I'd like to write a nested handler for consumption of json using rapidjson.
I've modeled my basic handler along the lines of the official simplereader example. This is fine for flat structures, but now I need to expand the parsing to nested objects as well.
The way I see it, I can either
have a central handler that keeps track of various domain objects to create and subsequent parse values into, or
I can change handler while parsing
Technically, I know how to do 1., but 2. seems like a neater solution, if possible.
Is it possible to change handlers mid-stream? Is there a best practice for doing this?
Thanks!
You can delegate the events to other handlers. This is often done by:
Applying the State Pattern internally in your custom handler. So that the handler can delegate the events to the current state object via polymorphism (a.k.a. virtual functions).
Using switch-case to do the delegation with an enum.
The first one has advantage if you need to deal with recursive structure. You can push the pointers of state objects in a stack.

Best design pattern for event listeners

Using C++ & MFC I've created a class which makes it easier to add drag/drop functionality to a CWnd object. There is nothing special about it really. Currently it is used like so:
Create CDropListener object
Call a method on the CDropListener object saying which file extension you want it to react to and a function pointer of what to call when a file is dropped
Register this with the CWnd object
Delete the CDropListener object when the window is destroyed
Repeat all of the above steps if you want different file extensions for a different CWnd
It is a bit cumbersome having to create a class member variable for each listener, and I was just wondering which design pattern would be more suitable for this. I only need the member objects so that I can delete them at the end. I thought I could just use an array to store them in and it would simplify it a bit, but I also thought there might be a better way where you can just call a static function similar to DropListener::RegisterListener(CWnd* wnd, CString& extension, void(*callback) callback) and it handles all of the creating / registering / deleting for you.
I'm not familiar with MFC but from an OO point of view your design can be improved.
First identify what aspects of your requirements are most likely to change and then identify what the interfaces needed to isolate those changes are:
Changes:
The thing you want to listen for (the event)
The action you want to take (the callback)
Interfaces:
The mechanism of adding a callback related to an event to the event notifier
The mechanism of calling the callback from the notifier
So you need an Event interface, a Callback interface, and a Notifier interface.
In C++ there is a handy thing called std::function<T> where T is any callable type (a pointer to a function, a functor, a lambda). So you should probably use that for encapsulating your callbacks to give your user more freedom.
Then how may event types do you want to support? This will tell you whether you need to support different Event objects as well as how your registration will look:
// For example if you support just `Drop` events:
void addDropListener(std::function<T> callback);
// If you support many events:
void addListener(Event::Type evType, std::function<T> callback);
Once you have answered that you need to decide what a "callback" looks like (T in the above examples). This could return a value (if you want success verification) or throw a particular exception type (make sure to document the contract). Then ask if you want a copy of the event that was fired (usually you would). Assuming you are happy to only be notified of errors via exceptions then you can typedef the expected std::function like this:
typedef std::function<void (const Event&)> EventCallback;
I recommend then that your Notifier implementer use a std::vector<EventCallback> or std::map<Event::Type, std:vector<EventCallback>. The first one is useful if you want to only support one event type or to call all listeners for all events. The second is handy when you want to only notify listeners of certain types of event.
In any case if you are finding that you need to change your class code to accommodate minor changes to behaviour then you need some refactoring.
Hope that helped. :)