From 10cc649f452abca7ad4a03d11df629a2669753e4 Mon Sep 17 00:00:00 2001 From: Frank DeMarco Date: Sat, 18 May 2019 21:25:27 -0400 Subject: [PATCH] unsubscribe automatically at destruction --- demo/Demo.cpp | 6 +++++- demo/Makefile | 7 ++++--- src/Delegate.cpp | 6 +++--- src/Delegate.hpp | 38 +++++++++++++++++++++++++++++++++----- src/Game.cpp | 5 +++++ src/Game.hpp | 1 + src/Node.cpp | 1 + src/Node.hpp | 2 +- 8 files changed, 53 insertions(+), 13 deletions(-) diff --git a/demo/Demo.cpp b/demo/Demo.cpp index 482a336..a90897d 100644 --- a/demo/Demo.cpp +++ b/demo/Demo.cpp @@ -129,9 +129,13 @@ struct Demo : Game Mix_PlayMusic(music, -1); load_gl_context(); delegate.subscribe(&Demo::respond, this); - // Input input = Input(this); + Input* l = new Input(this); + delete l; // input.print_branch(); // mushroom.print_branch(); + // Input* i = new Input(this); + // get_delegate().unsubscribe(i); + // delete i; } std::string get_class_name() diff --git a/demo/Makefile b/demo/Makefile index 770ec23..818e5e1 100644 --- a/demo/Makefile +++ b/demo/Makefile @@ -38,10 +38,11 @@ $(GLEW_DIR)%.o: $(GLEW_DIR)%.c $(GLEW_DIR)%.h $(SFW_SRC_DIR)Sprite.o: $(addprefix $(SFW_SRC_DIR),Game.*pp Location.*pp Node.*pp) $(SFW_SRC_DIR)Game.o: $(addprefix $(SFW_SRC_DIR),Sprite.*pp Configuration.*pp Delegate.*pp Display.*pp \ - Recorder.*pp Node.*pp) -$(SFW_SRC_DIR)Node.o: $(addprefix $(SFW_SRC_DIR),Game.*pp Configuration.*pp Node.*pp) + Recorder.*pp Node.*pp Input.*pp) +$(SFW_SRC_DIR)Node.o: $(addprefix $(SFW_SRC_DIR),Game.*pp Configuration.*pp Delegate.*pp) $(SFW_SRC_DIR)Animation.o: $(addprefix $(SFW_SRC_DIR),Timer.*pp) -$(SFW_SRC_DIR)Recorder.o: $(addprefix $(SFW_SRC_DIR),extension.*pp Node.*pp) +$(SFW_SRC_DIR)Recorder.o: $(addprefix $(SFW_SRC_DIR),extension.*pp Node.*pp Delegate.*pp) +$(SFW_SRC_DIR)Input.o: $(addprefix $(SFW_SRC_DIR),Delegate.*pp) $(SFW_SRC_DIR)%.o: $(addprefix $(SFW_SRC_DIR),%.cpp %.hpp) $(CPPC_LINUX) $(CPP_FLAGS) $(SDL_FLAGS) $< -o $@ diff --git a/src/Delegate.cpp b/src/Delegate.cpp index e3a8bbc..4a0be9d 100644 --- a/src/Delegate.cpp +++ b/src/Delegate.cpp @@ -4,7 +4,7 @@ int Delegate::command_event_type = SDL_RegisterEvents(1); Delegate::Delegate(Node* parent) : Node(parent) {} -void Delegate::add_subscriber(subscriber s, int type) +void Delegate::add_subscriber(Subscriber s, int type) { if (subscribers.count(type) == 0) { @@ -22,9 +22,9 @@ void Delegate::dispatch() { if (event.type == iter->first) { - for (subscriber s : iter->second) + for (Subscriber s : iter->second) { - s(event); + s.f(event); } } } diff --git a/src/Delegate.hpp b/src/Delegate.hpp index 19d0c0e..195889f 100644 --- a/src/Delegate.hpp +++ b/src/Delegate.hpp @@ -5,29 +5,57 @@ #include #include #include +#include +#include #include "Node.hpp" #include "SDL.h" -typedef std::function subscriber; +struct Subscriber +{ + std::function f; + void* o; +}; struct Delegate : Node { - std::map> subscribers; + std::map> subscribers; static int command_event_type; Delegate(Node*); - void add_subscriber(subscriber, int); + void add_subscriber(Subscriber, int); void dispatch(); bool compare(SDL_Event&, std::string); - void remove_subscriber(subscriber, int); template void subscribe(void(T::*f)(SDL_Event&), T* o, int type = command_event_type) { - add_subscriber(std::bind(f, o, std::placeholders::_1), type); + add_subscriber({std::bind(f, o, std::placeholders::_1), o}, type); + } + + template + void unsubscribe(T* p) + { + const std::type_info& info = typeid(p); + for (auto t = subscribers.begin(); t != subscribers.end(); t++) + { + for (auto s = t->second.begin(); s != t->second.end();) + { + std::cout << p << " " << s->o << " " << s->f.target_type().name() << " " << info.name() << " " << + std::type_index(info).name() << " " << + (s->f.target_type() == info) << std::endl; + if (p == s->o) + { + s = t->second.erase(s); + } + else + { + s++; + } + } + } } }; diff --git a/src/Game.cpp b/src/Game.cpp index 129b56b..b25a44e 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -59,6 +59,11 @@ Game::Game() } } +Game::~Game() +{ + get_delegate().unsubscribe(this); +} + void Game::print_error(std::string message) { std::cerr << message << std::endl; diff --git a/src/Game.hpp b/src/Game.hpp index fd46b91..a98314e 100644 --- a/src/Game.hpp +++ b/src/Game.hpp @@ -45,6 +45,7 @@ struct Game : Node Input input = Input(this); Game(); + ~Game(); void print_error(std::string); void print_sdl_error(std::string); void print_gl_attributes(); diff --git a/src/Node.cpp b/src/Node.cpp index 76affab..78bc695 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -14,6 +14,7 @@ Node::~Node() { std::cout << "Destructing "; print_branch(); + get_delegate().unsubscribe(this); } nlohmann::json& Node::get_configuration() diff --git a/src/Node.hpp b/src/Node.hpp index 1af7cca..1030c13 100644 --- a/src/Node.hpp +++ b/src/Node.hpp @@ -20,7 +20,7 @@ struct Node Node(); Node(Node*); - ~Node(); + virtual ~Node(); Game* get_root(); nlohmann::json& get_configuration(); Delegate& get_delegate();