4
\$\begingroup\$

This is a class which provides a simple event system mechanism:

template <typename T>
class EventChannel
{
private:
    using idType = unsigned int;
    static idType& getId()
    {
        static idType id = 0;
        return id;
    }

    static std::unordered_map<idType, std::function<bool(T)>>& getHandlers()
    {
        static std::unordered_map<idType, std::function<bool(T)>> handlers;
        return handlers;
    }
public:
    static idType regiterListener(std::function<bool(T)> listener)
    {
        auto& id = getId();
        id++;
        getHandlers()[id] = listener;
        return id;
    }
    static void tringgerEvent(T e)
    {
        for (const auto& h : getHandlers())
        {
            h.second(e);
        }
    }
    static void removeListener(idType listener_id)
    {
        getHandlers().erase(listener_id);
    }
};

and the usage is like this:

struct TouchEvent
{
    int t_id;
    float x;
    float y;
};
//just for convenience
template <typename T>
void DISPATCH_EVENT(T t)
{
    EventChannel<T>::tringgerEvent(t);
}
...

auto lid = EventChannel<TouchEvent>::regiterListener([](TouchEvent ev)->bool
{
    cout << "got touch " << ev.t_id << "\n"; return false; 
});

DISPATCH_EVENT(TouchEvent{ 10, 2, 4 });

The output would be just as you would expect:

got touch 10

It's also possible to remove the previously set listener:

EventChannel<TouchEvent>::removeListener(lid);

Any insight on what I've done badly wrong would be much appreciated.

\$\endgroup\$
2
  • \$\begingroup\$ it's obvious that ideally you should be able to remove listeners just by knowing their ids. in the current implementation you also need to know which event type was it registered for. \$\endgroup\$
    – kdcode
    Apr 30, 2016 at 21:36
  • \$\begingroup\$ I am mostly concerned about using it with polymorphic event types, Which can be prohibited by using type traits (eg std::is_pod) and static assertion. \$\endgroup\$
    – kdcode
    Apr 30, 2016 at 21:39

1 Answer 1

2
\$\begingroup\$

Your code looks very good to me. The only thing I would recommend changing is getId(). The fact that the function holds a static variable that is changed in regiterListener violates encapsulation a little bit. I would change it to:

static idType getNextId()
{
    static idType id = 0;
    return ++id;
}

and use it as:

static idType regiterListener(std::function<bool(T)> listener)
{
    auto id = getNextId();
    getHandlers()[id] = listener;
    return id;
}
\$\endgroup\$
1
  • \$\begingroup\$ Would you please take a look at the edits I posted here \$\endgroup\$
    – kdcode
    May 2, 2016 at 16:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.