unsubscribe automatically at destruction

This commit is contained in:
Frank DeMarco 2019-05-18 21:25:27 -04:00
parent e45806f8bc
commit 10cc649f45
8 changed files with 53 additions and 13 deletions

View File

@ -129,9 +129,13 @@ struct Demo : Game
Mix_PlayMusic(music, -1); Mix_PlayMusic(music, -1);
load_gl_context(); load_gl_context();
delegate.subscribe(&Demo::respond, this); delegate.subscribe(&Demo::respond, this);
// Input input = Input(this); Input* l = new Input(this);
delete l;
// input.print_branch(); // input.print_branch();
// mushroom.print_branch(); // mushroom.print_branch();
// Input* i = new Input(this);
// get_delegate().unsubscribe(i);
// delete i;
} }
std::string get_class_name() std::string get_class_name()

View File

@ -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)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 \ $(SFW_SRC_DIR)Game.o: $(addprefix $(SFW_SRC_DIR),Sprite.*pp Configuration.*pp Delegate.*pp Display.*pp \
Recorder.*pp Node.*pp) Recorder.*pp Node.*pp Input.*pp)
$(SFW_SRC_DIR)Node.o: $(addprefix $(SFW_SRC_DIR),Game.*pp Configuration.*pp Node.*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)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) $(SFW_SRC_DIR)%.o: $(addprefix $(SFW_SRC_DIR),%.cpp %.hpp)
$(CPPC_LINUX) $(CPP_FLAGS) $(SDL_FLAGS) $< -o $@ $(CPPC_LINUX) $(CPP_FLAGS) $(SDL_FLAGS) $< -o $@

View File

@ -4,7 +4,7 @@ int Delegate::command_event_type = SDL_RegisterEvents(1);
Delegate::Delegate(Node* parent) : Node(parent) {} 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) if (subscribers.count(type) == 0)
{ {
@ -22,9 +22,9 @@ void Delegate::dispatch()
{ {
if (event.type == iter->first) if (event.type == iter->first)
{ {
for (subscriber s : iter->second) for (Subscriber s : iter->second)
{ {
s(event); s.f(event);
} }
} }
} }

View File

@ -5,29 +5,57 @@
#include <map> #include <map>
#include <list> #include <list>
#include <functional> #include <functional>
#include <typeinfo>
#include <typeindex>
#include "Node.hpp" #include "Node.hpp"
#include "SDL.h" #include "SDL.h"
typedef std::function<void(SDL_Event&)> subscriber; struct Subscriber
{
std::function<void(SDL_Event&)> f;
void* o;
};
struct Delegate : Node struct Delegate : Node
{ {
std::map<int, std::vector<subscriber>> subscribers; std::map<int, std::vector<Subscriber>> subscribers;
static int command_event_type; static int command_event_type;
Delegate(Node*); Delegate(Node*);
void add_subscriber(subscriber, int); void add_subscriber(Subscriber, int);
void dispatch(); void dispatch();
bool compare(SDL_Event&, std::string); bool compare(SDL_Event&, std::string);
void remove_subscriber(subscriber, int);
template<typename T> template<typename T>
void subscribe(void(T::*f)(SDL_Event&), T* o, int type = command_event_type) 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<typename T>
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++;
}
}
}
} }
}; };

View File

@ -59,6 +59,11 @@ Game::Game()
} }
} }
Game::~Game()
{
get_delegate().unsubscribe(this);
}
void Game::print_error(std::string message) void Game::print_error(std::string message)
{ {
std::cerr << message << std::endl; std::cerr << message << std::endl;

View File

@ -45,6 +45,7 @@ struct Game : Node
Input input = Input(this); Input input = Input(this);
Game(); Game();
~Game();
void print_error(std::string); void print_error(std::string);
void print_sdl_error(std::string); void print_sdl_error(std::string);
void print_gl_attributes(); void print_gl_attributes();

View File

@ -14,6 +14,7 @@ Node::~Node()
{ {
std::cout << "Destructing "; std::cout << "Destructing ";
print_branch(); print_branch();
get_delegate().unsubscribe(this);
} }
nlohmann::json& Node::get_configuration() nlohmann::json& Node::get_configuration()

View File

@ -20,7 +20,7 @@ struct Node
Node(); Node();
Node(Node*); Node(Node*);
~Node(); virtual ~Node();
Game* get_root(); Game* get_root();
nlohmann::json& get_configuration(); nlohmann::json& get_configuration();
Delegate& get_delegate(); Delegate& get_delegate();