Giter Site home page Giter Site logo

Comments (10)

wqking avatar wqking commented on May 26, 2024

So my suggestion is that can you add another example about using the policies?

The tutorial with that remarks has already demonstrated it. :-)
But it's a good idea to put the key/mouse tutorial there as a more comprehensive example, I will do it.

Generally, people don't need to use two different dispatcher objects for different event/signal classes, which make the library more flexible!

You don't need to use different dispatcher objects, you only need to use one dispatcher for the base event class, then inherit all events from that base. A quick pseudo example is (same to the key/mouse example), you have,
struct Event;, struct KeyEvent : Event;, then you can have dispatcher with prototype of void (const Event &), then you can dispatch dispatcher.dispatch(KeyEvent()). Or use std::unique_ptr or std::shared_ptr instead of reference, which should be used if you use EventQueue.

The feature you advised is already supported in the Heterogeneous classes. There is a section in the documents for them.
However, the heter classes are mostly for Proof of Concept purpose rather than massive usage, so it was not well maintained.
It has some disadvantage to the core classes (homogeneous classes) than,

  1. The code is much more difficult to write, and the code is very complicated. Though it's not problem for the users.
  2. It has slightly memory and performance overhead than core classes, though I didn't benchmark it.
  3. The API interface may not be same as core classes, because some API is impossible or very difficult to implement in heter. I can't remember which function, though.

From view of architecture, I don't recommend to use the Heterogeneous classes, or the way you proposal that the callback may have different prototypes, because,

  1. When you have many kinds of event types, you may quickly lose control on the large amount of event types, event classes, and event callback prototypes.
  2. It's difficult to communicate with other developers. Beside documenting the event type and classes, you need to document the prototypes that you used?
  3. Though we can do the Heterogeneous event system in C++, in most applications in the world the main stream is homogeneous, not only C++, but also Java, C#, etc, so we'd better keep in the main stream.
  4. Same as the point 2 in the "disadvantage" list above, more flexibility means more cost. Event system is very essential in an application, so performance should be critical.

However, all above are my personal opinion. If more people/projects are interesting in heterogeneous event system, we may evolve the current implementation better.

from eventpp.

asmwarrior avatar asmwarrior commented on May 26, 2024

Hi, thanks for the response and explanation.

I just looked at the document: eventpp/heterogeneous.md at 6e5f6ee45d6e9b1aad8d6bb533cafd1333b2a8e6 · wqking/eventpp, and as you said, the heterogeneous classes means the callback function have different prototypes, such as in the document:

eventpp::EventDispatcher<int, void ()> dispatcher;
dispatcher.appendListener(3, []() {}); // OK
dispatcher.appendListener(3, [](std::string) {}); // wrong, can't listen for void(std::string)

But what I need may be a little different, the callback function have some similar prototype, for example, I searched on the StackOverflow site, and this question is exact problem I have:

c++ - Typesafe implementation of an event system - Stack Overflow

// Create the on event functions
std::function<void(const ClickEvent &)> onClickFunction = [](const ClickEvent & event)
{
    std::cout << std::endl << "Mouse clicked at position: " << event.x << event.y;
};

std::function<void(const RenderNodeCreatedEvent &)> onRenderNodeCreatedFunction = [](const RenderNodeCreatedEvent & event)
{
    std::cout << std::endl << "Render node created with id: " << event.renderNodeId;
};

// Create the events
ClickEvent clickEvent;
clickEvent.x = 300.f;
clickEvent.y = 255.5f;

RenderNodeCreatedEvent renderNodeCreatedEvent;
renderNodeCreatedEvent.renderNodeId = 26234628374324;

// Create the event manager and subscribe the event functions
EventManager eventManager;
eventManager.Subscribe(onClickFunction);
eventManager.Subscribe(onRenderNodeCreatedFunction);

// Raise the events
eventManager.Raise(clickEvent);
eventManager.Raise(renderNodeCreatedEvent);

You can see, the event class is the only argument for the each event handler, and either ClickEvent and RenderNodeCreatedEvent are derived from the same base class Event.

from eventpp.

wqking avatar wqking commented on May 26, 2024

"similar prototype" is still different prototype, heterogeneous classes support your example.

from eventpp.

asmwarrior avatar asmwarrior commented on May 26, 2024

"similar prototype" is still different prototype, heterogeneous classes support your example.

Indeed, they are different prototypes.

Meanwhile, I create a gist sample event_system.cpp file in github, which I follow the way mentioned in c++ - ECS Event/Messaging implementation - Code Review Stack Exchange.

The trick is the argument type is stored in the callback wrapper, once the event happens, a map(in the code, it use std::vector<std::vector>> is used to locate the associated callbacks and call them(a static cast is need here).

I'm really not sure how the eventpp library did in the heterogeneous classes.

Thanks.

from eventpp.

wqking avatar wqking commented on May 26, 2024

There is no tutorial for heter classes, but you can check the unit test
You can replace the prototype void (const MyEvent &) with const PLAYER_HIT& event, void (const MyEvent &, int) with const PLAYER_LVL_UP& event, etc.
That test is to test ArgumentPassingMode, but you can ignore it safetly.

from eventpp.

asmwarrior avatar asmwarrior commented on May 26, 2024

Thanks for the reply.

TEST_CASE("HeterEventDispatcher, getEvent, ArgumentPassingIncludeEvent")
{
struct MyEvent {
int type;
int param;
};
struct EventPolicies
{
using ArgumentPassingMode = eventpp::ArgumentPassingIncludeEvent;
static int getEvent(const MyEvent & e) {
return e.type;
}
static int getEvent(const MyEvent & e, int) {
return e.type;
}
};
eventpp::HeterEventDispatcher<int, eventpp::HeterTuple<void (const MyEvent &), void (const MyEvent &, int)>, EventPolicies> dispatcher;
constexpr int event = 3;
std::vector<int> dataList(2);
dispatcher.appendListener(event, [&dataList](const MyEvent & e) {
dataList[0] = e.param;
});
dispatcher.appendListener(event, [&dataList](const MyEvent & e, int i) {
dataList[1] = e.param + i;
});
REQUIRE(dataList == std::vector<int>{ 0, 0 });
dispatcher.dispatch(MyEvent{ event, 5 });
REQUIRE(dataList == std::vector<int>{ 5, 0 });
dispatcher.dispatch(MyEvent{ event, 5 }, 3);
REQUIRE(dataList == std::vector<int>{ 5, 8 });
}

Sorry, I am not quite understand the method you suggested.

There is no tutorial for heter classes, but you can check the unit test You can replace the prototype void (const MyEvent &) with const PLAYER_HIT& event, void (const MyEvent &, int) with const PLAYER_LVL_UP& event, etc. That test is to test ArgumentPassingMode, but you can ignore it safetly.

I can replace the the const MyEvent &) in the following code:

dispatcher.appendListener(event, [&dataList](const MyEvent & e) {
dataList[0] = e.param;
});
dispatcher.appendListener(event, [&dataList](const MyEvent & e, int i) {
dataList[1] = e.param + i;
});

But How can I replace the MyEvent definition?

struct MyEvent {
int type;
int param;
};

from eventpp.

wqking avatar wqking commented on May 26, 2024

I will try to add some tutorials.

from eventpp.

wqking avatar wqking commented on May 26, 2024

I added more tutorials for EventQueue. Tutorial 4 is what you are looking for.
I also added tutorial for HeterEventDispatcher. It's not in document, but you can check the code

from eventpp.

wqking avatar wqking commented on May 26, 2024

The tutorials are enough for demonstrating how it works. I will close this issue.

from eventpp.

asmwarrior avatar asmwarrior commented on May 26, 2024

Thanks for your tutorial!

from eventpp.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.