Refactor library dispatch stuff to dedicated namespace

This commit is contained in:
Ilari Liusvaara 2013-12-19 01:04:42 +02:00
parent dd486e7ff8
commit f89395dbc1
18 changed files with 158 additions and 105 deletions

View file

@ -255,23 +255,23 @@ private:
void dispatch_set_error_streams(std::ostream* stream); void dispatch_set_error_streams(std::ostream* stream);
extern struct dispatcher<> notify_autohold_reconfigure; extern struct dispatch::source<> notify_autohold_reconfigure;
extern struct dispatcher<unsigned, unsigned, unsigned, bool> notify_autohold_update; extern struct dispatch::source<unsigned, unsigned, unsigned, bool> notify_autohold_update;
extern struct dispatcher<unsigned, unsigned, unsigned, unsigned, unsigned> notify_autofire_update; extern struct dispatch::source<unsigned, unsigned, unsigned, unsigned, unsigned> notify_autofire_update;
extern struct dispatcher<> notify_close; extern struct dispatch::source<> notify_close;
extern struct dispatcher<framebuffer<false>&> notify_set_screen; extern struct dispatch::source<framebuffer<false>&> notify_set_screen;
extern struct dispatcher<std::pair<std::string, std::string>> notify_sound_change; extern struct dispatch::source<std::pair<std::string, std::string>> notify_sound_change;
extern struct dispatcher<> notify_screen_update; extern struct dispatch::source<> notify_screen_update;
extern struct dispatcher<> notify_status_update; extern struct dispatch::source<> notify_status_update;
extern struct dispatcher<bool> notify_sound_unmute; extern struct dispatch::source<bool> notify_sound_unmute;
extern struct dispatcher<bool> notify_mode_change; extern struct dispatch::source<bool> notify_mode_change;
extern struct dispatcher<> notify_core_change; extern struct dispatch::source<> notify_core_change;
extern struct dispatcher<> notify_title_change; extern struct dispatch::source<> notify_title_change;
extern struct dispatcher<bool> notify_core_changed; extern struct dispatch::source<bool> notify_core_changed;
extern struct dispatcher<> notify_new_core; extern struct dispatch::source<> notify_new_core;
extern struct dispatcher<> notify_voice_stream_change; extern struct dispatch::source<> notify_voice_stream_change;
extern struct dispatcher<> notify_vu_change; extern struct dispatch::source<> notify_vu_change;
extern struct dispatcher<> notify_subtitle_change; extern struct dispatch::source<> notify_subtitle_change;
extern struct dispatcher<unsigned, unsigned, int> notify_multitrack_change; extern struct dispatch::source<unsigned, unsigned, int> notify_multitrack_change;
#endif #endif

View file

@ -8,51 +8,86 @@
#include <functional> #include <functional>
#include "threadtypes.hpp" #include "threadtypes.hpp"
mutex_class& dispatch_global_init_lock(); namespace dispatch
template<typename... T> struct dispatcher;
template<typename... T> struct dispatch_target
{ {
dispatch_target() mutex_class& global_init_lock();
template<typename... T> struct source;
/**
* Dispatch target handler.
*/
template<typename... T> struct target
{
/**
* Create a new target handler.
*/
target()
{ {
src = NULL; src = NULL;
fn = dummy; fn = dummy;
} }
inline ~dispatch_target(); /**
inline void set(dispatcher<T...>& d, std::function<void(T...)> _fn); * Destroy a target, detaching it from source.
*/
inline ~target();
/**
* Connect a target to given source and give a handler.
*
* Parameter d: The source to connect to.
* Parameter _fn: The function to use as handler.
*/
inline void set(source<T...>& d, std::function<void(T...)> _fn);
private: private:
static void dummy(T... args) {}; static void dummy(T... args) {};
void set_source(dispatcher<T...>* d) { src = d; } void set_source(source<T...>* d) { src = d; }
void call(T... args) { fn(args...); } void call(T... args) { fn(args...); }
dispatcher<T...>* src; source<T...>* src;
std::function<void(T...)> fn; std::function<void(T...)> fn;
friend class dispatcher<T...>; friend class source<T...>;
}; };
template<typename... T> struct dispatcher /**
* Dispatch source (event generator).
*/
template<typename... T> struct source
{ {
dispatcher(const char* _name) /**
* Create a new event source.
*
* Parameter _name: The name of the event.
*/
source(const char* _name)
{ {
init(); init();
name = _name; name = _name;
} }
~dispatcher() /**
* Destory an event source.
*
* All targets are disconnected.
*/
~source()
{ {
delete _targets; delete _targets;
delete lck; delete lck;
lck = NULL; lck = NULL;
} }
/**
* Send an event.
*
* Parameter args: The arguments to send.
*/
void operator()(T... args) void operator()(T... args)
{ {
init(); init();
uint64_t k = 0; uint64_t k = 0;
typename std::map<uint64_t, dispatch_target<T...>*>::iterator i; typename std::map<uint64_t, target<T...>*>::iterator i;
lck->lock(); lck->lock();
i = targets().lower_bound(k); i = targets().lower_bound(k);
while(i != targets().end()) { while(i != targets().end()) {
k = i->first + 1; k = i->first + 1;
dispatch_target<T...>* t = i->second; target<T...>* t = i->second;
lck->unlock(); lck->unlock();
try { try {
t->call(args...); t->call(args...);
@ -64,14 +99,24 @@ template<typename... T> struct dispatcher
} }
lck->unlock(); lck->unlock();
} }
void connect(dispatch_target<T...>& target) /**
* Connect a new target.
*
* Parameters target: The target to connect.
*/
void connect(target<T...>& target)
{ {
init(); init();
umutex_class h(*lck); umutex_class h(*lck);
targets()[next_cbseq++] = &target; targets()[next_cbseq++] = &target;
target.set_source(this); target.set_source(this);
} }
void disconnect(dispatch_target<T...>& target) /**
* Disconnect a target.
*
* Parameters target: The target to disconnect.
*/
void disconnect(target<T...>& target)
{ {
init(); init();
if(!lck) if(!lck)
@ -84,6 +129,11 @@ template<typename... T> struct dispatcher
} }
target.set_source(NULL); target.set_source(NULL);
} }
/**
* Set stream to send error messages to.
*
* Parameter to: The stream (if NULL, use std::cerr).
*/
void errors_to(std::ostream* to) void errors_to(std::ostream* to)
{ {
errstrm = to ? to : &std::cerr; errstrm = to ? to : &std::cerr;
@ -93,7 +143,7 @@ private:
{ {
if(inited) if(inited)
return; return;
umutex_class h(dispatch_global_init_lock()); umutex_class h(global_init_lock());
if(inited) if(inited)
return; return;
errstrm = &std::cerr; errstrm = &std::cerr;
@ -104,32 +154,32 @@ private:
inited = true; inited = true;
} }
mutex_class* lck; mutex_class* lck;
std::map<uint64_t, dispatch_target<T...>*>& targets() std::map<uint64_t, target<T...>*>& targets()
{ {
if(!_targets) _targets = new std::map<uint64_t, dispatch_target<T...>*>; if(!_targets) _targets = new std::map<uint64_t, target<T...>*>;
return *_targets; return *_targets;
} }
std::map<uint64_t, dispatch_target<T...>*>* _targets; std::map<uint64_t, target<T...>*>* _targets;
uint64_t next_cbseq; uint64_t next_cbseq;
std::ostream* errstrm; std::ostream* errstrm;
const char* name; const char* name;
bool inited; bool inited;
dispatcher(const dispatcher<T...>&); source(const source<T...>&);
dispatcher<T...>& operator=(const dispatcher<T...>&); source<T...>& operator=(const source<T...>&);
}; };
template <typename... T> dispatch_target<T...>::~dispatch_target() template <typename... T> target<T...>::~target()
{ {
if(src) if(src)
src->disconnect(*this); src->disconnect(*this);
} }
template <typename... T> void dispatch_target<T...>::set(dispatcher<T...>& d, std::function<void(T...)> _fn) template <typename... T> void target<T...>::set(source<T...>& d, std::function<void(T...)> _fn)
{ {
fn = _fn; fn = _fn;
src = &d; src = &d;
if(src) if(src)
src->connect(*this); src->connect(*this);
} }
}
#endif #endif

View file

@ -20,7 +20,7 @@ private:
int wxid_range_low; int wxid_range_low;
int wxid_range_high; int wxid_range_high;
std::function<void(core_type* name)> callback; std::function<void(core_type* name)> callback;
struct dispatch_target<> corelistener; struct dispatch::target<> corelistener;
}; };
#endif #endif

View file

@ -17,7 +17,7 @@ public:
void update(); void update();
bool any_enabled(); bool any_enabled();
private: private:
struct dispatch_target<> corechange; struct dispatch::target<> corechange;
wxWindow* pwin; wxWindow* pwin;
int wxid_range_low; int wxid_range_low;
int wxid_range_high; int wxid_range_high;

View file

@ -76,11 +76,11 @@ private:
void* sounddev2; void* sounddev2;
void* dmenu; void* dmenu;
wxTimer* focus_timer; wxTimer* focus_timer;
struct dispatch_target<> corechange; struct dispatch::target<> corechange;
struct dispatch_target<> titlechange; struct dispatch::target<> titlechange;
struct dispatch_target<> newcore; struct dispatch::target<> newcore;
struct dispatch_target<bool> unmuted; struct dispatch::target<bool> unmuted;
struct dispatch_target<bool> modechange; struct dispatch::target<bool> modechange;
}; };
#endif #endif

View file

@ -515,7 +515,7 @@ namespace
{ {
ncore.set(notify_new_core, []() { init_buttonmap(); }); ncore.set(notify_new_core, []() { init_buttonmap(); });
} }
struct dispatch_target<> ncore; struct dispatch::target<> ncore;
} coresnoop; } coresnoop;
} }

View file

@ -31,7 +31,7 @@ namespace
cb2_list dummy_cb2; //Always empty. cb2_list dummy_cb2; //Always empty.
uint64_t xmask = 1; uint64_t xmask = 1;
std::function<void()> tracelog_change_cb; std::function<void()> tracelog_change_cb;
struct dispatch_target<> corechange; struct dispatch::target<> corechange;
bool corechange_r = false; bool corechange_r = false;
struct tracelog_file struct tracelog_file

View file

@ -88,7 +88,7 @@ uint64_t gameinfo_struct::get_rerecords() const throw()
namespace namespace
{ {
globalwrap<std::list<information_dispatch*>> dispatch; globalwrap<std::list<information_dispatch*>> _dispatch;
globalwrap<std::list<information_dispatch*>> dispatch_audio; globalwrap<std::list<information_dispatch*>> dispatch_audio;
uint32_t srate_n = 32000; uint32_t srate_n = 32000;
uint32_t srate_d = 1; uint32_t srate_d = 1;
@ -99,7 +99,7 @@ namespace
information_dispatch::information_dispatch(const std::string& name) throw(std::bad_alloc) information_dispatch::information_dispatch(const std::string& name) throw(std::bad_alloc)
{ {
target_name = name; target_name = name;
dispatch().push_back(this); _dispatch().push_back(this);
known_if_dumper = false; known_if_dumper = false;
marked_as_dumper = false; marked_as_dumper = false;
notified_as_dumper = false; notified_as_dumper = false;
@ -107,9 +107,9 @@ information_dispatch::information_dispatch(const std::string& name) throw(std::b
information_dispatch::~information_dispatch() throw() information_dispatch::~information_dispatch() throw()
{ {
for(auto i = dispatch().begin(); i != dispatch().end(); ++i) { for(auto i = _dispatch().begin(); i != _dispatch().end(); ++i) {
if(*i == this) { if(*i == this) {
dispatch().erase(i); _dispatch().erase(i);
break; break;
} }
} }
@ -120,7 +120,7 @@ information_dispatch::~information_dispatch() throw()
} }
} }
if(notified_as_dumper) if(notified_as_dumper)
for(auto& i : dispatch()) { for(auto& i : _dispatch()) {
START_EH_BLOCK START_EH_BLOCK
i->on_destroy_dumper(target_name); i->on_destroy_dumper(target_name);
END_EH_BLOCK(i, "on_destroy_dumper"); END_EH_BLOCK(i, "on_destroy_dumper");
@ -135,7 +135,7 @@ void information_dispatch::on_frame(struct framebuffer_raw& _frame, uint32_t fps
void information_dispatch::do_frame(struct framebuffer_raw& _frame, uint32_t fps_n, uint32_t fps_d) throw() void information_dispatch::do_frame(struct framebuffer_raw& _frame, uint32_t fps_n, uint32_t fps_d) throw()
{ {
update_dumpers(); update_dumpers();
for(auto& i : dispatch()) { for(auto& i : _dispatch()) {
START_EH_BLOCK START_EH_BLOCK
i->on_frame(_frame, fps_n, fps_d); i->on_frame(_frame, fps_n, fps_d);
END_EH_BLOCK(i, "on_frame"); END_EH_BLOCK(i, "on_frame");
@ -165,7 +165,7 @@ void information_dispatch::on_dump_end()
void information_dispatch::do_dump_end() throw() void information_dispatch::do_dump_end() throw()
{ {
update_dumpers(); update_dumpers();
for(auto& i : dispatch()) { for(auto& i : _dispatch()) {
START_EH_BLOCK START_EH_BLOCK
i->on_dump_end(); i->on_dump_end();
END_EH_BLOCK(i, "on_dump_end"); END_EH_BLOCK(i, "on_dump_end");
@ -194,7 +194,7 @@ void information_dispatch::do_sound_rate(uint32_t rate_n, uint32_t rate_d) throw
return; return;
srate_n = rate_n; srate_n = rate_n;
srate_d = rate_d; srate_d = rate_d;
for(auto& i : dispatch()) { for(auto& i : _dispatch()) {
START_EH_BLOCK START_EH_BLOCK
i->on_sound_rate(rate_n, rate_d); i->on_sound_rate(rate_n, rate_d);
END_EH_BLOCK(i, "on_sound_rate"); END_EH_BLOCK(i, "on_sound_rate");
@ -219,7 +219,7 @@ void information_dispatch::do_gameinfo(const struct gameinfo_struct& gi) throw()
} catch(...) { } catch(...) {
OOM_panic(); OOM_panic();
} }
for(auto& i : dispatch()) { for(auto& i : _dispatch()) {
START_EH_BLOCK START_EH_BLOCK
i->on_gameinfo(sgi); i->on_gameinfo(sgi);
END_EH_BLOCK(i, "on_gameinfo"); END_EH_BLOCK(i, "on_gameinfo");
@ -250,7 +250,7 @@ unsigned information_dispatch::get_dumper_count() throw()
{ {
update_dumpers(true); update_dumpers(true);
unsigned count = 0; unsigned count = 0;
for(auto& i : dispatch()) for(auto& i : _dispatch())
if(i->marked_as_dumper) if(i->marked_as_dumper)
count++; count++;
if(!recursive) { if(!recursive) {
@ -266,7 +266,7 @@ std::set<std::string> information_dispatch::get_dumpers() throw(std::bad_alloc)
update_dumpers(); update_dumpers();
std::set<std::string> r; std::set<std::string> r;
try { try {
for(auto& i : dispatch()) for(auto& i : _dispatch())
if(i->notified_as_dumper) if(i->notified_as_dumper)
r.insert(i->get_name()); r.insert(i->get_name());
} catch(...) { } catch(...) {
@ -283,13 +283,13 @@ const std::string& information_dispatch::get_name() throw()
void information_dispatch::update_dumpers(bool nocalls) throw() void information_dispatch::update_dumpers(bool nocalls) throw()
{ {
for(auto& i : dispatch()) { for(auto& i : _dispatch()) {
if(!i->known_if_dumper) { if(!i->known_if_dumper) {
i->marked_as_dumper = i->get_dumper_flag(); i->marked_as_dumper = i->get_dumper_flag();
i->known_if_dumper = true; i->known_if_dumper = true;
} }
if(i->marked_as_dumper && !i->notified_as_dumper && !nocalls) { if(i->marked_as_dumper && !i->notified_as_dumper && !nocalls) {
for(auto& j : dispatch()) { for(auto& j : _dispatch()) {
START_EH_BLOCK START_EH_BLOCK
j->on_new_dumper(i->target_name); j->on_new_dumper(i->target_name);
END_EH_BLOCK(j, "on_new_dumper"); END_EH_BLOCK(j, "on_new_dumper");
@ -313,7 +313,7 @@ void information_dispatch::do_dumper_update() throw()
{ {
if(in_global_ctors()) if(in_global_ctors())
return; return;
for(auto& i : dispatch()) { for(auto& i : _dispatch()) {
START_EH_BLOCK START_EH_BLOCK
i->on_dumper_update(); i->on_dumper_update();
END_EH_BLOCK(i, "on_dumper_update"); END_EH_BLOCK(i, "on_dumper_update");
@ -342,21 +342,21 @@ void dispatch_set_error_streams(std::ostream* stream)
notify_title_change.errors_to(stream); notify_title_change.errors_to(stream);
} }
struct dispatcher<> notify_autohold_reconfigure("autohold_reconfigure"); struct dispatch::source<> notify_autohold_reconfigure("autohold_reconfigure");
struct dispatcher<unsigned, unsigned, unsigned, bool> notify_autohold_update("autohold_update"); struct dispatch::source<unsigned, unsigned, unsigned, bool> notify_autohold_update("autohold_update");
struct dispatcher<unsigned, unsigned, unsigned, unsigned, unsigned> notify_autofire_update("autofire_update"); struct dispatch::source<unsigned, unsigned, unsigned, unsigned, unsigned> notify_autofire_update("autofire_update");
struct dispatcher<> notify_close("notify_close"); struct dispatch::source<> notify_close("notify_close");
struct dispatcher<framebuffer<false>&> notify_set_screen("set_screen"); struct dispatch::source<framebuffer<false>&> notify_set_screen("set_screen");
struct dispatcher<std::pair<std::string, std::string>> notify_sound_change("sound_change"); struct dispatch::source<std::pair<std::string, std::string>> notify_sound_change("sound_change");
struct dispatcher<> notify_screen_update("screen_update"); struct dispatch::source<> notify_screen_update("screen_update");
struct dispatcher<> notify_status_update("status_update"); struct dispatch::source<> notify_status_update("status_update");
struct dispatcher<bool> notify_sound_unmute("sound_unmute"); struct dispatch::source<bool> notify_sound_unmute("sound_unmute");
struct dispatcher<bool> notify_mode_change("mode_change"); struct dispatch::source<bool> notify_mode_change("mode_change");
struct dispatcher<> notify_core_change("core_change"); struct dispatch::source<> notify_core_change("core_change");
struct dispatcher<bool> notify_core_changed("core_changed"); struct dispatch::source<bool> notify_core_changed("core_changed");
struct dispatcher<> notify_new_core("new_core"); struct dispatch::source<> notify_new_core("new_core");
struct dispatcher<> notify_voice_stream_change("voice_stream_change"); struct dispatch::source<> notify_voice_stream_change("voice_stream_change");
struct dispatcher<> notify_vu_change("vu_change"); struct dispatch::source<> notify_vu_change("vu_change");
struct dispatcher<> notify_subtitle_change("subtitle_change"); struct dispatch::source<> notify_subtitle_change("subtitle_change");
struct dispatcher<unsigned, unsigned, int> notify_multitrack_change("multitrack_change"); struct dispatch::source<unsigned, unsigned, int> notify_multitrack_change("multitrack_change");
struct dispatcher<> notify_title_change("title_change"); struct dispatch::source<> notify_title_change("title_change");

View file

@ -1017,7 +1017,7 @@ namespace
update_movie_state(); update_movie_state();
} }
private: private:
struct dispatch_target<> closenotify; struct dispatch::target<> closenotify;
} mywcb; } mywcb;
//If there is a pending load, perform it. Return 1 on successful load, 0 if nothing to load, -1 on load //If there is a pending load, perform it. Return 1 on successful load, 0 if nothing to load, -1 on load

View file

@ -526,9 +526,9 @@ namespace
setscreen.set(notify_set_screen, [](framebuffer<false>& scr) { our_screen = &scr; }); setscreen.set(notify_set_screen, [](framebuffer<false>& scr) { our_screen = &scr; });
} }
private: private:
struct dispatch_target<> screenupdate; struct dispatch::target<> screenupdate;
struct dispatch_target<> statusupdate; struct dispatch::target<> statusupdate;
struct dispatch_target<framebuffer<false>&> setscreen; struct dispatch::target<framebuffer<false>&> setscreen;
} x; } x;
} }

View file

@ -1,7 +1,10 @@
#include "dispatch.hpp" #include "dispatch.hpp"
mutex_class& dispatch_global_init_lock() namespace dispatch
{
mutex_class& global_init_lock()
{ {
static mutex_class m; static mutex_class m;
return m; return m;
} }
}

View file

@ -29,9 +29,9 @@ public:
void on_wclose(wxCloseEvent& e); void on_wclose(wxCloseEvent& e);
void on_checkbox(wxCommandEvent& e); void on_checkbox(wxCommandEvent& e);
private: private:
struct dispatch_target<unsigned, unsigned, unsigned, bool> ahupdate; struct dispatch::target<unsigned, unsigned, unsigned, bool> ahupdate;
struct dispatch_target<unsigned, unsigned, unsigned, unsigned, unsigned> afupdate; struct dispatch::target<unsigned, unsigned, unsigned, unsigned, unsigned> afupdate;
struct dispatch_target<> ahreconfigure; struct dispatch::target<> ahreconfigure;
struct control_triple struct control_triple
{ {

View file

@ -876,7 +876,7 @@ private:
_panel* hpanel; _panel* hpanel;
wxMenu* valuemenu; wxMenu* valuemenu;
wxMenu* typemenu; wxMenu* typemenu;
struct dispatch_target<bool> corechange; struct dispatch::target<bool> corechange;
unsigned current_vma; unsigned current_vma;
std::vector<std::string> vma_names; std::vector<std::string> vma_names;
std::map<unsigned, bool> vma_endians; std::map<unsigned, bool> vma_endians;

View file

@ -40,9 +40,9 @@ public:
void on_wclose(wxCloseEvent& e); void on_wclose(wxCloseEvent& e);
void on_control(wxCommandEvent& e); void on_control(wxCommandEvent& e);
private: private:
struct dispatch_target<> ahreconfigure; struct dispatch::target<> ahreconfigure;
struct dispatch_target<bool> ahmodechange; struct dispatch::target<bool> ahmodechange;
struct dispatch_target<unsigned, unsigned, int> ahmtchange; struct dispatch::target<unsigned, unsigned, int> ahmtchange;
struct controller_info struct controller_info
{ {
unsigned port; unsigned port;

View file

@ -45,7 +45,7 @@ private:
wxButton* _delete; wxButton* _delete;
wxButton* close; wxButton* close;
std::map<int, subdata> subtexts; std::map<int, subdata> subtexts;
struct dispatch_target<> subchange; struct dispatch::target<> subchange;
}; };
namespace namespace

View file

@ -93,7 +93,7 @@ public:
void on_keyboard_down(wxKeyEvent& e); void on_keyboard_down(wxKeyEvent& e);
void call_screen_update(); void call_screen_update();
private: private:
struct dispatch_target<> ahreconfigure; struct dispatch::target<> ahreconfigure;
struct xypanel; struct xypanel;
struct control_triple struct control_triple
{ {

View file

@ -57,8 +57,8 @@ private:
wxButton* unloadbutton; wxButton* unloadbutton;
wxButton* refreshbutton; wxButton* refreshbutton;
wxButton* closebutton; wxButton* closebutton;
struct dispatch_target<> corechange; struct dispatch::target<> corechange;
struct dispatch_target<> vstreamchange; struct dispatch::target<> vstreamchange;
}; };
wxeditor_voicesub::wxeditor_voicesub(wxWindow* parent) wxeditor_voicesub::wxeditor_voicesub(wxWindow* parent)

View file

@ -202,7 +202,7 @@ private:
volatile bool update_sent; volatile bool update_sent;
bool closing; bool closing;
wxButton* closebutton; wxButton* closebutton;
struct dispatch_target<> vulistener; struct dispatch::target<> vulistener;
_vupanel* vupanel; _vupanel* vupanel;
wxStaticText* rate; wxStaticText* rate;
wxSlider* gamevol; wxSlider* gamevol;
@ -214,8 +214,8 @@ private:
wxComboBox* pdev; wxComboBox* pdev;
wxComboBox* rdev; wxComboBox* rdev;
wxCheckBox* mute; wxCheckBox* mute;
struct dispatch_target<bool> unmuted; struct dispatch::target<bool> unmuted;
struct dispatch_target<std::pair<std::string, std::string>> devchange; struct dispatch::target<std::pair<std::string, std::string>> devchange;
}; };
wxwin_vumeter::wxwin_vumeter(wxWindow* parent) wxwin_vumeter::wxwin_vumeter(wxWindow* parent)