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);
extern struct dispatcher<> notify_autohold_reconfigure;
extern struct dispatcher<unsigned, unsigned, unsigned, bool> notify_autohold_update;
extern struct dispatcher<unsigned, unsigned, unsigned, unsigned, unsigned> notify_autofire_update;
extern struct dispatcher<> notify_close;
extern struct dispatcher<framebuffer<false>&> notify_set_screen;
extern struct dispatcher<std::pair<std::string, std::string>> notify_sound_change;
extern struct dispatcher<> notify_screen_update;
extern struct dispatcher<> notify_status_update;
extern struct dispatcher<bool> notify_sound_unmute;
extern struct dispatcher<bool> notify_mode_change;
extern struct dispatcher<> notify_core_change;
extern struct dispatcher<> notify_title_change;
extern struct dispatcher<bool> notify_core_changed;
extern struct dispatcher<> notify_new_core;
extern struct dispatcher<> notify_voice_stream_change;
extern struct dispatcher<> notify_vu_change;
extern struct dispatcher<> notify_subtitle_change;
extern struct dispatcher<unsigned, unsigned, int> notify_multitrack_change;
extern struct dispatch::source<> notify_autohold_reconfigure;
extern struct dispatch::source<unsigned, unsigned, unsigned, bool> notify_autohold_update;
extern struct dispatch::source<unsigned, unsigned, unsigned, unsigned, unsigned> notify_autofire_update;
extern struct dispatch::source<> notify_close;
extern struct dispatch::source<framebuffer<false>&> notify_set_screen;
extern struct dispatch::source<std::pair<std::string, std::string>> notify_sound_change;
extern struct dispatch::source<> notify_screen_update;
extern struct dispatch::source<> notify_status_update;
extern struct dispatch::source<bool> notify_sound_unmute;
extern struct dispatch::source<bool> notify_mode_change;
extern struct dispatch::source<> notify_core_change;
extern struct dispatch::source<> notify_title_change;
extern struct dispatch::source<bool> notify_core_changed;
extern struct dispatch::source<> notify_new_core;
extern struct dispatch::source<> notify_voice_stream_change;
extern struct dispatch::source<> notify_vu_change;
extern struct dispatch::source<> notify_subtitle_change;
extern struct dispatch::source<unsigned, unsigned, int> notify_multitrack_change;
#endif

View file

@ -8,51 +8,86 @@
#include <functional>
#include "threadtypes.hpp"
mutex_class& dispatch_global_init_lock();
template<typename... T> struct dispatcher;
template<typename... T> struct dispatch_target
namespace dispatch
{
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;
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:
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...); }
dispatcher<T...>* src;
source<T...>* src;
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();
name = _name;
}
~dispatcher()
/**
* Destory an event source.
*
* All targets are disconnected.
*/
~source()
{
delete _targets;
delete lck;
lck = NULL;
}
/**
* Send an event.
*
* Parameter args: The arguments to send.
*/
void operator()(T... args)
{
init();
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();
i = targets().lower_bound(k);
while(i != targets().end()) {
k = i->first + 1;
dispatch_target<T...>* t = i->second;
target<T...>* t = i->second;
lck->unlock();
try {
t->call(args...);
@ -64,14 +99,24 @@ template<typename... T> struct dispatcher
}
lck->unlock();
}
void connect(dispatch_target<T...>& target)
/**
* Connect a new target.
*
* Parameters target: The target to connect.
*/
void connect(target<T...>& target)
{
init();
umutex_class h(*lck);
targets()[next_cbseq++] = &target;
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();
if(!lck)
@ -84,6 +129,11 @@ template<typename... T> struct dispatcher
}
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)
{
errstrm = to ? to : &std::cerr;
@ -93,7 +143,7 @@ private:
{
if(inited)
return;
umutex_class h(dispatch_global_init_lock());
umutex_class h(global_init_lock());
if(inited)
return;
errstrm = &std::cerr;
@ -104,32 +154,32 @@ private:
inited = true;
}
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;
}
std::map<uint64_t, dispatch_target<T...>*>* _targets;
std::map<uint64_t, target<T...>*>* _targets;
uint64_t next_cbseq;
std::ostream* errstrm;
const char* name;
bool inited;
dispatcher(const dispatcher<T...>&);
dispatcher<T...>& operator=(const dispatcher<T...>&);
source(const source<T...>&);
source<T...>& operator=(const source<T...>&);
};
template <typename... T> dispatch_target<T...>::~dispatch_target()
template <typename... T> target<T...>::~target()
{
if(src)
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;
src = &d;
if(src)
src->connect(*this);
}
}
#endif

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1017,7 +1017,7 @@ namespace
update_movie_state();
}
private:
struct dispatch_target<> closenotify;
struct dispatch::target<> closenotify;
} mywcb;
//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; });
}
private:
struct dispatch_target<> screenupdate;
struct dispatch_target<> statusupdate;
struct dispatch_target<framebuffer<false>&> setscreen;
struct dispatch::target<> screenupdate;
struct dispatch::target<> statusupdate;
struct dispatch::target<framebuffer<false>&> setscreen;
} x;
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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