Make keymapper threadsafe
The keymapper is now threadsafe, instead of being only called from the emulation thread.
This commit is contained in:
parent
5761188ebb
commit
2176427609
6 changed files with 288 additions and 122 deletions
|
@ -31,6 +31,10 @@ struct mutex
|
|||
* Create a mutex. The returned mutex can be deleted using delete.
|
||||
*/
|
||||
static mutex& aquire() throw(std::bad_alloc);
|
||||
/**
|
||||
* Create a recursive mutex. The returned mutex can be deleted using delete.
|
||||
*/
|
||||
static mutex& aquire_rec() throw(std::bad_alloc);
|
||||
/**
|
||||
* Destroy a mutex.
|
||||
*/
|
||||
|
|
|
@ -78,6 +78,23 @@ namespace
|
|||
globalwrap<std::map<std::string, std::string>> modifier_linkages;
|
||||
globalwrap<std::map<std::string, keygroup*>> keygroups;
|
||||
|
||||
//Return the recursive mutex.
|
||||
mutex& kmlock()
|
||||
{
|
||||
static mutex& m = mutex::aquire_rec();
|
||||
return m;
|
||||
}
|
||||
|
||||
class kmlock_hold
|
||||
{
|
||||
public:
|
||||
kmlock_hold() { kmlock().lock(); }
|
||||
~kmlock_hold() { kmlock().unlock(); }
|
||||
private:
|
||||
kmlock_hold(const kmlock_hold& k);
|
||||
kmlock_hold& operator=(const kmlock_hold& k);
|
||||
};
|
||||
|
||||
//Returns orig if not linked.
|
||||
const modifier* get_linked_modifier(const modifier* orig)
|
||||
{
|
||||
|
@ -90,23 +107,27 @@ namespace
|
|||
|
||||
modifier::modifier(const std::string& name) throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
known_modifiers()[modname = name] = this;
|
||||
}
|
||||
|
||||
modifier::modifier(const std::string& name, const std::string& linkgroup) throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
known_modifiers()[modname = name] = this;
|
||||
modifier_linkages()[name] = linkgroup;
|
||||
}
|
||||
|
||||
modifier::~modifier() throw()
|
||||
{
|
||||
kmlock_hold lck;
|
||||
known_modifiers().erase(modname);
|
||||
modifier_linkages().erase(modname);
|
||||
}
|
||||
|
||||
std::set<std::string> modifier::get_set() throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
std::set<std::string> r;
|
||||
for(auto i : known_modifiers())
|
||||
r.insert(i.first);
|
||||
|
@ -115,6 +136,7 @@ std::set<std::string> modifier::get_set() throw(std::bad_alloc)
|
|||
|
||||
modifier& modifier::lookup(const std::string& name) throw(std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
if(!known_modifiers().count(name)) {
|
||||
std::ostringstream x;
|
||||
x << "Invalid modifier '" << name << "'";
|
||||
|
@ -125,11 +147,13 @@ modifier& modifier::lookup(const std::string& name) throw(std::bad_alloc, std::r
|
|||
|
||||
std::string modifier::name() const throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
return modname;
|
||||
}
|
||||
|
||||
std::string modifier::linked_name() const throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
const modifier* p = get_linked_modifier(this);
|
||||
if(p == this)
|
||||
return "";
|
||||
|
@ -139,18 +163,21 @@ std::string modifier::linked_name() const throw(std::bad_alloc)
|
|||
|
||||
void modifier_set::add(const modifier& mod, bool really) throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
if(really)
|
||||
set.insert(&mod);
|
||||
}
|
||||
|
||||
void modifier_set::remove(const modifier& mod, bool really) throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
if(really)
|
||||
set.erase(&mod);
|
||||
}
|
||||
|
||||
modifier_set modifier_set::construct(const std::string& _modifiers) throw(std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
modifier_set set;
|
||||
std::string modifiers = _modifiers;
|
||||
while(modifiers != "") {
|
||||
|
@ -169,6 +196,7 @@ modifier_set modifier_set::construct(const std::string& _modifiers) throw(std::b
|
|||
|
||||
bool modifier_set::valid(const modifier_set& set, const modifier_set& mask) throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
//No element can be together with its linkage group.
|
||||
for(auto i : set.set) {
|
||||
const modifier* j = get_linked_modifier(i);
|
||||
|
@ -191,6 +219,7 @@ bool modifier_set::valid(const modifier_set& set, const modifier_set& mask) thro
|
|||
|
||||
bool modifier_set::operator==(const modifier_set& m) const throw()
|
||||
{
|
||||
kmlock_hold lck;
|
||||
for(auto i : set)
|
||||
if(!m.set.count(i))
|
||||
return false;
|
||||
|
@ -202,6 +231,7 @@ bool modifier_set::operator==(const modifier_set& m) const throw()
|
|||
|
||||
std::ostream& operator<<(std::ostream& os, const modifier_set& m)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
os << "<modset:";
|
||||
for(auto i : m.set)
|
||||
os << i->name() << " ";
|
||||
|
@ -212,6 +242,7 @@ std::ostream& operator<<(std::ostream& os, const modifier_set& m)
|
|||
bool modifier_set::triggers(const modifier_set& set, const modifier_set& trigger, const modifier_set& mask)
|
||||
throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
for(auto i : mask.set) {
|
||||
bool ok = false;
|
||||
//OK iff at least one of:
|
||||
|
@ -254,16 +285,19 @@ bool modifier_set::triggers(const modifier_set& set, const modifier_set& trigger
|
|||
|
||||
std::string keygroup::name() throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
return keyname;
|
||||
}
|
||||
|
||||
const std::string& keygroup::get_class()
|
||||
{
|
||||
kmlock_hold lck;
|
||||
return clazz;
|
||||
}
|
||||
|
||||
struct keygroup::parameters keygroup::get_parameters()
|
||||
{
|
||||
kmlock_hold lck;
|
||||
parameters p;
|
||||
p.ktype = ktype;
|
||||
p.cal_left = cal_left;
|
||||
|
@ -276,6 +310,7 @@ struct keygroup::parameters keygroup::get_parameters()
|
|||
|
||||
std::map<std::string, struct keygroup::parameters> keygroup::get_all_parameters()
|
||||
{
|
||||
kmlock_hold lck;
|
||||
std::map<std::string, struct parameters> ret;
|
||||
for(auto i : keygroups())
|
||||
ret[i.first] = i.second->get_parameters();
|
||||
|
@ -284,6 +319,7 @@ std::map<std::string, struct keygroup::parameters> keygroup::get_all_parameters(
|
|||
|
||||
keygroup::keygroup(const std::string& name, const std::string& _clazz, enum type t) throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
keygroups()[keyname = name] = this;
|
||||
clazz = _clazz;
|
||||
ktype = t;
|
||||
|
@ -298,11 +334,13 @@ keygroup::keygroup(const std::string& name, const std::string& _clazz, enum type
|
|||
|
||||
keygroup::~keygroup() throw()
|
||||
{
|
||||
kmlock_hold lck;
|
||||
keygroups().erase(keyname);
|
||||
}
|
||||
|
||||
void keygroup::change_type(enum type t) throw()
|
||||
{
|
||||
kmlock_hold lck;
|
||||
ktype = t;
|
||||
state = 0;
|
||||
if(requests_hook)
|
||||
|
@ -311,6 +349,7 @@ void keygroup::change_type(enum type t) throw()
|
|||
|
||||
void keygroup::request_hook_callback(bool state)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
requests_hook = state;
|
||||
}
|
||||
|
||||
|
@ -318,6 +357,7 @@ void keygroup::request_hook_callback(bool state)
|
|||
std::pair<keygroup*, unsigned> keygroup::lookup(const std::string& name) throw(std::bad_alloc,
|
||||
std::runtime_error)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
if(keygroups().count(name))
|
||||
return std::make_pair(keygroups()[name], 0);
|
||||
std::string prefix = name;
|
||||
|
@ -344,6 +384,7 @@ std::pair<keygroup*, unsigned> keygroup::lookup(const std::string& name) throw(s
|
|||
|
||||
void keygroup::change_calibration(short left, short center, short right, double tolerance)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
cal_left = left;
|
||||
cal_center = center;
|
||||
cal_right = right;
|
||||
|
@ -354,6 +395,7 @@ void keygroup::change_calibration(short left, short center, short right, double
|
|||
|
||||
double keygroup::compensate(short value)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
if(ktype == KT_HAT || ktype == KT_KEY || ktype == KT_DISABLED || ktype == KT_MOUSE)
|
||||
return value; //These can't be calibrated.
|
||||
if(value <= cal_left)
|
||||
|
@ -370,6 +412,7 @@ double keygroup::compensate(short value)
|
|||
|
||||
double keygroup::compensate2(double value)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
switch(ktype) {
|
||||
case KT_DISABLED:
|
||||
case KT_MOUSE:
|
||||
|
@ -398,6 +441,7 @@ double keygroup::compensate2(double value)
|
|||
|
||||
void keygroup::set_position(short pos, const modifier_set& modifiers) throw()
|
||||
{
|
||||
kmlock_hold lck;
|
||||
last_rawval = pos;
|
||||
if(requests_hook)
|
||||
lua_callback_keyhook(keyname, get_parameters());
|
||||
|
@ -461,26 +505,32 @@ void keygroup::set_position(short pos, const modifier_set& modifiers) throw()
|
|||
|
||||
void keygroup::run_listeners(const modifier_set& modifiers, unsigned subkey, bool polarity, bool really, double x)
|
||||
{
|
||||
if(!really)
|
||||
return;
|
||||
std::string name = keyname;
|
||||
if(ktype == KT_AXIS_PAIR && subkey == 0)
|
||||
name = name + "+";
|
||||
if(ktype == KT_AXIS_PAIR && subkey == 1)
|
||||
name = name + "-";
|
||||
if(ktype == KT_HAT && subkey == 0)
|
||||
name = name + "n";
|
||||
if(ktype == KT_HAT && subkey == 1)
|
||||
name = name + "e";
|
||||
if(ktype == KT_HAT && subkey == 2)
|
||||
name = name + "s";
|
||||
if(ktype == KT_HAT && subkey == 3)
|
||||
name = name + "w";
|
||||
information_dispatch::do_key_event(modifiers, *this, subkey, polarity, name);
|
||||
std::string name;
|
||||
modifier_set _modifiers = modifiers;
|
||||
{
|
||||
if(!really)
|
||||
return;
|
||||
kmlock_hold lck;
|
||||
name = keyname;
|
||||
if(ktype == KT_AXIS_PAIR && subkey == 0)
|
||||
name = name + "+";
|
||||
if(ktype == KT_AXIS_PAIR && subkey == 1)
|
||||
name = name + "-";
|
||||
if(ktype == KT_HAT && subkey == 0)
|
||||
name = name + "n";
|
||||
if(ktype == KT_HAT && subkey == 1)
|
||||
name = name + "e";
|
||||
if(ktype == KT_HAT && subkey == 2)
|
||||
name = name + "s";
|
||||
if(ktype == KT_HAT && subkey == 3)
|
||||
name = name + "w";
|
||||
}
|
||||
information_dispatch::do_key_event(_modifiers, *this, subkey, polarity, name);
|
||||
}
|
||||
|
||||
keygroup* keygroup::lookup_by_name(const std::string& name) throw()
|
||||
{
|
||||
kmlock_hold lck;
|
||||
if(keygroups().count(name))
|
||||
return keygroups()[name];
|
||||
else
|
||||
|
@ -489,6 +539,7 @@ keygroup* keygroup::lookup_by_name(const std::string& name) throw()
|
|||
|
||||
std::set<std::string> keygroup::get_axis_set() throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
std::set<std::string> r;
|
||||
for(auto i : keygroups()) {
|
||||
keygroup::parameters p = i.second->get_parameters();
|
||||
|
@ -514,6 +565,7 @@ std::set<std::string> keygroup::get_axis_set() throw(std::bad_alloc)
|
|||
|
||||
std::set<std::string> keygroup::get_keys() throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
std::set<std::string> r;
|
||||
for(auto i : keygroups()) {
|
||||
switch(i.second->ktype) {
|
||||
|
@ -546,12 +598,12 @@ std::set<std::string> keygroup::get_keys() throw(std::bad_alloc)
|
|||
|
||||
signed keygroup::get_value()
|
||||
{
|
||||
kmlock_hold lck;
|
||||
return state;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
function_ptr_command<const std::string&> set_axis("set-axis", "Set mode of Joystick axis",
|
||||
"Syntax: set-axis <axis> <options>...\nKnown options: disabled, axis, axis-inverse, pressure0-\n"
|
||||
"pressure0+, pressure-0, pressure-+, pressure+0, pressure+-\nminus=<val>, zero=<val>, plus=<val>\n"
|
||||
|
@ -721,6 +773,7 @@ namespace
|
|||
|
||||
std::map<triple, keybind_data*>& keybindings()
|
||||
{
|
||||
kmlock_hold lck;
|
||||
static std::map<triple, keybind_data*> x;
|
||||
return x;
|
||||
}
|
||||
|
@ -729,35 +782,42 @@ namespace
|
|||
void keymapper::bind(std::string mod, std::string modmask, std::string keyname, std::string command)
|
||||
throw(std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
triple k(mod, modmask, keyname);
|
||||
modifier_set _mod = modifier_set::construct(mod);
|
||||
modifier_set _modmask = modifier_set::construct(modmask);
|
||||
if(!modifier_set::valid(_mod, _modmask))
|
||||
throw std::runtime_error("Invalid modifiers");
|
||||
auto g = keygroup::lookup(keyname);
|
||||
if(!keybindings().count(k)) {
|
||||
keybindings()[k] = new keybind_data;
|
||||
keybindings()[k]->mod = _mod;
|
||||
keybindings()[k]->modmask = _modmask;
|
||||
keybindings()[k]->group = g.first;
|
||||
keybindings()[k]->subkey = g.second;
|
||||
{
|
||||
kmlock_hold lck;
|
||||
triple k(mod, modmask, keyname);
|
||||
modifier_set _mod = modifier_set::construct(mod);
|
||||
modifier_set _modmask = modifier_set::construct(modmask);
|
||||
if(!modifier_set::valid(_mod, _modmask))
|
||||
throw std::runtime_error("Invalid modifiers");
|
||||
auto g = keygroup::lookup(keyname);
|
||||
if(!keybindings().count(k)) {
|
||||
keybindings()[k] = new keybind_data;
|
||||
keybindings()[k]->mod = _mod;
|
||||
keybindings()[k]->modmask = _modmask;
|
||||
keybindings()[k]->group = g.first;
|
||||
keybindings()[k]->subkey = g.second;
|
||||
}
|
||||
keybindings()[k]->command = command;
|
||||
}
|
||||
keybindings()[k]->command = command;
|
||||
inverse_key::notify_update(mod + "/" + modmask + "|" + keyname, command);
|
||||
}
|
||||
void keymapper::unbind(std::string mod, std::string modmask, std::string keyname) throw(std::bad_alloc,
|
||||
std::runtime_error)
|
||||
{
|
||||
triple k(mod, modmask, keyname);
|
||||
if(!keybindings().count(k))
|
||||
throw std::runtime_error("Key is not bound");
|
||||
delete keybindings()[k];
|
||||
keybindings().erase(k);
|
||||
{
|
||||
kmlock_hold lck;
|
||||
triple k(mod, modmask, keyname);
|
||||
if(!keybindings().count(k))
|
||||
throw std::runtime_error("Key is not bound");
|
||||
delete keybindings()[k];
|
||||
keybindings().erase(k);
|
||||
}
|
||||
inverse_key::notify_update(mod + "/" + modmask + "|" + keyname, "");
|
||||
}
|
||||
|
||||
void keymapper::dumpbindings() throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
for(auto i : keybindings()) {
|
||||
messages << "bind-key ";
|
||||
if(i.first.a != "" || i.first.b != "")
|
||||
|
@ -768,6 +828,7 @@ void keymapper::dumpbindings() throw(std::bad_alloc)
|
|||
|
||||
std::set<std::string> keymapper::get_bindings() throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
std::set<std::string> r;
|
||||
for(auto i : keybindings())
|
||||
r.insert(i.first.a + "/" + i.first.b + "|" + i.first.c);
|
||||
|
@ -776,6 +837,7 @@ std::set<std::string> keymapper::get_bindings() throw(std::bad_alloc)
|
|||
|
||||
std::string keymapper::get_command_for(const std::string& keyspec) throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
triple k("", "", "");
|
||||
try {
|
||||
k = parse_to_triple(keyspec);
|
||||
|
@ -800,6 +862,7 @@ void keymapper::bind_for(const std::string& keyspec, const std::string& cmd) thr
|
|||
|
||||
inverse_key::inverse_key(const std::string& command, const std::string& name) throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
cmd = command;
|
||||
oname = name;
|
||||
ikeys().insert(this);
|
||||
|
@ -813,44 +876,52 @@ inverse_key::inverse_key(const std::string& command, const std::string& name) th
|
|||
|
||||
inverse_key::~inverse_key()
|
||||
{
|
||||
kmlock_hold lck;
|
||||
ikeys().erase(this);
|
||||
forkey().erase(cmd);
|
||||
}
|
||||
|
||||
std::set<inverse_key*> inverse_key::get_ikeys() throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
return ikeys();
|
||||
}
|
||||
|
||||
std::string inverse_key::getname() throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
return oname;
|
||||
}
|
||||
|
||||
inverse_key* inverse_key::get_for(const std::string& command) throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
return forkey().count(command) ? forkey()[command] : NULL;
|
||||
}
|
||||
|
||||
std::set<inverse_key*>& inverse_key::ikeys()
|
||||
{
|
||||
kmlock_hold lck;
|
||||
static std::set<inverse_key*> x;
|
||||
return x;
|
||||
}
|
||||
|
||||
std::map<std::string, inverse_key*>& inverse_key::forkey()
|
||||
{
|
||||
kmlock_hold lck;
|
||||
static std::map<std::string, inverse_key*> x;
|
||||
return x;
|
||||
}
|
||||
|
||||
std::string inverse_key::get(bool primary) throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
return primary ? primary_spec : secondary_spec;
|
||||
}
|
||||
|
||||
void inverse_key::clear(bool primary) throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
if(primary) {
|
||||
if(primary_spec != "")
|
||||
keymapper::bind_for(primary_spec, "");
|
||||
|
@ -870,6 +941,7 @@ void inverse_key::clear(bool primary) throw(std::bad_alloc)
|
|||
|
||||
void inverse_key::set(std::string keyspec, bool primary) throw(std::bad_alloc)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
if(keyspec == "") {
|
||||
clear(primary);
|
||||
return;
|
||||
|
@ -891,6 +963,7 @@ void inverse_key::set(std::string keyspec, bool primary) throw(std::bad_alloc)
|
|||
|
||||
void inverse_key::addkey(const std::string& keyspec)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
if(primary_spec == "" || primary_spec == keyspec)
|
||||
primary_spec = keyspec;
|
||||
else if(secondary_spec == "")
|
||||
|
@ -899,6 +972,7 @@ void inverse_key::addkey(const std::string& keyspec)
|
|||
|
||||
void inverse_key::notify_update(const std::string& keyspec, const std::string& command)
|
||||
{
|
||||
kmlock_hold lck;
|
||||
for(auto k : ikeys()) {
|
||||
bool u = false;
|
||||
if(k->primary_spec == keyspec || k->secondary_spec == keyspec) {
|
||||
|
|
|
@ -24,6 +24,11 @@ mutex& mutex::aquire() throw(std::bad_alloc)
|
|||
return *new dummy_mutex();
|
||||
}
|
||||
|
||||
mutex& mutex::aquire_rec() throw(std::bad_alloc)
|
||||
{
|
||||
return *new dummy_mutex();
|
||||
}
|
||||
|
||||
struct dummy_condition : public condition
|
||||
{
|
||||
dummy_condition(mutex& m);
|
||||
|
|
|
@ -13,6 +13,18 @@ struct sdl_mutex : public mutex
|
|||
SDL_mutex* m;
|
||||
};
|
||||
|
||||
struct sdl_rec_mutex : public mutex
|
||||
{
|
||||
sdl_rec_mutex() throw(std::bad_alloc);
|
||||
~sdl_rec_mutex() throw();
|
||||
void lock() throw();
|
||||
void unlock() throw();
|
||||
SDL_mutex* m;
|
||||
volatile bool locked;
|
||||
uint32_t owner;
|
||||
uint32_t count;
|
||||
};
|
||||
|
||||
sdl_mutex::sdl_mutex() throw(std::bad_alloc)
|
||||
{
|
||||
m = SDL_CreateMutex();
|
||||
|
@ -25,6 +37,21 @@ sdl_mutex::~sdl_mutex() throw()
|
|||
SDL_DestroyMutex(m);
|
||||
}
|
||||
|
||||
sdl_rec_mutex::sdl_rec_mutex() throw(std::bad_alloc)
|
||||
{
|
||||
m = SDL_CreateMutex();
|
||||
if(!m)
|
||||
throw std::bad_alloc();
|
||||
locked = false;
|
||||
owner = 0;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
sdl_rec_mutex::~sdl_rec_mutex() throw()
|
||||
{
|
||||
SDL_DestroyMutex(m);
|
||||
}
|
||||
|
||||
void sdl_mutex::lock() throw()
|
||||
{
|
||||
SDL_mutexP(m);
|
||||
|
@ -35,11 +62,42 @@ void sdl_mutex::unlock() throw()
|
|||
SDL_mutexV(m);
|
||||
}
|
||||
|
||||
void sdl_rec_mutex::lock() throw()
|
||||
{
|
||||
uint32_t our_id = SDL_ThreadID();
|
||||
if(locked && owner == our_id) {
|
||||
//Owned by us, increment lock count.
|
||||
++count;
|
||||
return;
|
||||
}
|
||||
SDL_mutexP(m);
|
||||
locked = true;
|
||||
owner = our_id;
|
||||
count = 1;
|
||||
}
|
||||
|
||||
void sdl_rec_mutex::unlock() throw()
|
||||
{
|
||||
uint32_t our_id = SDL_ThreadID();
|
||||
if(!locked || owner != our_id)
|
||||
std::cerr << "Warning: Trying to unlock recursive lock locked by another thread!" << std::endl;
|
||||
if(!--count) {
|
||||
locked = false;
|
||||
owner = 0;
|
||||
SDL_mutexV(m);
|
||||
}
|
||||
}
|
||||
|
||||
mutex& mutex::aquire() throw(std::bad_alloc)
|
||||
{
|
||||
return *new sdl_mutex;
|
||||
}
|
||||
|
||||
mutex& mutex::aquire_rec() throw(std::bad_alloc)
|
||||
{
|
||||
return *new sdl_rec_mutex;
|
||||
}
|
||||
|
||||
struct sdl_condition : public condition
|
||||
{
|
||||
sdl_condition(mutex& m) throw(std::bad_alloc);
|
||||
|
|
|
@ -93,18 +93,16 @@ namespace
|
|||
std::set<std::string> mods, keys;
|
||||
|
||||
cleared = false;
|
||||
runemufn([&mods, &keys, &classes, &classeslist]() {
|
||||
std::set<std::string> x;
|
||||
mods = modifier::get_set();
|
||||
keys = keygroup::get_keys();
|
||||
for(auto i : keys) {
|
||||
std::string kclass = keygroup::lookup(i).first->get_class();
|
||||
if(!x.count(kclass))
|
||||
classeslist.push_back(towxstring(kclass));
|
||||
x.insert(kclass);
|
||||
classes[kclass].insert(i);
|
||||
}
|
||||
});
|
||||
std::set<std::string> x;
|
||||
mods = modifier::get_set();
|
||||
keys = keygroup::get_keys();
|
||||
for(auto i : keys) {
|
||||
std::string kclass = keygroup::lookup(i).first->get_class();
|
||||
if(!x.count(kclass))
|
||||
classeslist.push_back(towxstring(kclass));
|
||||
x.insert(kclass);
|
||||
classes[kclass].insert(i);
|
||||
}
|
||||
|
||||
Centre();
|
||||
top_s = new wxFlexGridSizer(2, 1, 0, 0);
|
||||
|
@ -384,11 +382,9 @@ wxeditor_esettings_joystick_aconfig::wxeditor_esettings_joystick_aconfig(wxWindo
|
|||
aname = _aname;
|
||||
keygroup::parameters params;
|
||||
|
||||
runemufn([aname, ¶ms]() {
|
||||
auto k = keygroup::lookup_by_name(aname);
|
||||
if(k)
|
||||
params = k->get_parameters();
|
||||
});
|
||||
auto k = keygroup::lookup_by_name(aname);
|
||||
if(k)
|
||||
params = k->get_parameters();
|
||||
|
||||
switch(params.ktype) {
|
||||
case keygroup::KT_DISABLED: didx = 0; break;
|
||||
|
@ -456,12 +452,10 @@ void wxeditor_esettings_joystick_aconfig::on_ok(wxCommandEvent& e)
|
|||
double ntol;
|
||||
keygroup* k;
|
||||
|
||||
runemufn([&k, aname, &_ctype]() {
|
||||
k = keygroup::lookup_by_name(aname);
|
||||
if(k)
|
||||
_ctype = k->get_parameters().ktype;
|
||||
});
|
||||
if(!k) {
|
||||
k = keygroup::lookup_by_name(aname);
|
||||
if(k)
|
||||
_ctype = k->get_parameters().ktype;
|
||||
else {
|
||||
//Axis gone away?
|
||||
EndModal(wxID_OK);
|
||||
return;
|
||||
|
@ -502,11 +496,9 @@ void wxeditor_esettings_joystick_aconfig::on_ok(wxCommandEvent& e)
|
|||
return;
|
||||
}
|
||||
|
||||
runemufn([&k, _ctype, _ntype, nlow, nmid, nhi, ntol]() {
|
||||
if(_ctype != _ntype)
|
||||
k->change_type(_ntype);
|
||||
k->change_calibration(nlow, nmid, nhi, ntol);
|
||||
});
|
||||
if(_ctype != _ntype)
|
||||
k->change_type(_ntype);
|
||||
k->change_calibration(nlow, nmid, nhi, ntol);
|
||||
EndModal(wxID_OK);
|
||||
}
|
||||
|
||||
|
@ -592,14 +584,12 @@ void wxeditor_esettings_joystick::refresh()
|
|||
{
|
||||
//Collect the new settings.
|
||||
std::map<std::string, keygroup::parameters> x;
|
||||
runemufn([&x]() {
|
||||
auto axisnames = keygroup::get_axis_set();
|
||||
for(auto i : axisnames) {
|
||||
keygroup* k = keygroup::lookup_by_name(i);
|
||||
if(k)
|
||||
x[i] = k->get_parameters();
|
||||
}
|
||||
});
|
||||
auto axisnames = keygroup::get_axis_set();
|
||||
for(auto i : axisnames) {
|
||||
keygroup* k = keygroup::lookup_by_name(i);
|
||||
if(k)
|
||||
x[i] = k->get_parameters();
|
||||
}
|
||||
|
||||
unsigned jcount = 0;
|
||||
for(auto i : x) {
|
||||
|
@ -1069,13 +1059,12 @@ void wxeditor_esettings_hotkeys::on_primary(wxCommandEvent& e)
|
|||
return;
|
||||
}
|
||||
try {
|
||||
std::string key;
|
||||
inverse_key* ik = realitems[name];
|
||||
if(!ik) {
|
||||
refresh();
|
||||
return;
|
||||
}
|
||||
runemufn([&key, ik]() { key = ik->get(true); });
|
||||
std::string key = ik->get(true);
|
||||
wxdialog_keyentry* d = new wxdialog_keyentry(this, "Specify key for " + name, key, true);
|
||||
if(d->ShowModal() == wxID_CANCEL) {
|
||||
d->Destroy();
|
||||
|
@ -1084,9 +1073,9 @@ void wxeditor_esettings_hotkeys::on_primary(wxCommandEvent& e)
|
|||
key = d->getkey();
|
||||
d->Destroy();
|
||||
if(key != "")
|
||||
runemufn([key, ik]() { ik->set(key, true); });
|
||||
ik->set(key, true);
|
||||
else
|
||||
runemufn([key, ik]() { ik->clear(true); });
|
||||
ik->clear(true);
|
||||
refresh();
|
||||
} catch(...) {
|
||||
refresh();
|
||||
|
@ -1101,13 +1090,12 @@ void wxeditor_esettings_hotkeys::on_secondary(wxCommandEvent& e)
|
|||
return;
|
||||
}
|
||||
try {
|
||||
std::string key;
|
||||
inverse_key* ik = realitems[name];
|
||||
if(!ik) {
|
||||
refresh();
|
||||
return;
|
||||
}
|
||||
runemufn([&key, ik]() { key = ik->get(false); });
|
||||
std::string key = ik->get(false);
|
||||
wxdialog_keyentry* d = new wxdialog_keyentry(this, "Specify key for " + name, key, true);
|
||||
if(d->ShowModal() == wxID_CANCEL) {
|
||||
d->Destroy();
|
||||
|
@ -1116,9 +1104,9 @@ void wxeditor_esettings_hotkeys::on_secondary(wxCommandEvent& e)
|
|||
key = d->getkey();
|
||||
d->Destroy();
|
||||
if(key != "")
|
||||
runemufn([key, ik]() { ik->set(key, false); });
|
||||
ik->set(key, false);
|
||||
else
|
||||
runemufn([key, ik]() { ik->clear(false); });
|
||||
ik->clear(false);
|
||||
refresh();
|
||||
} catch(...) {
|
||||
refresh();
|
||||
|
@ -1130,13 +1118,11 @@ void wxeditor_esettings_hotkeys::refresh()
|
|||
std::set<std::string> closure_additional;
|
||||
std::map<std::string, inverse_key*> keyorder;
|
||||
std::map<inverse_key*, std::pair<std::string, std::string>> data;
|
||||
runemufn([&data, &keyorder]() {
|
||||
auto x = inverse_key::get_ikeys();
|
||||
for(auto y : x) {
|
||||
keyorder[y->getname()] = y;
|
||||
data[y] = std::make_pair(y->get(true), y->get(false));
|
||||
}
|
||||
});
|
||||
auto x = inverse_key::get_ikeys();
|
||||
for(auto y : x) {
|
||||
keyorder[y->getname()] = y;
|
||||
data[y] = std::make_pair(y->get(true), y->get(false));
|
||||
}
|
||||
//Close keyorder with respect to parents.
|
||||
for(auto i : keyorder) {
|
||||
std::string tmp = i.first;
|
||||
|
@ -1283,22 +1269,15 @@ void wxeditor_esettings_bindings::on_add(wxCommandEvent& e)
|
|||
d->Destroy();
|
||||
|
||||
std::string newcommand = pick_text(this, "New binding", "Enter command for binding:", "");
|
||||
bool fault = false;
|
||||
std::string faulttext;
|
||||
runemufn([&fault, &faulttext, name, newcommand]() {
|
||||
try {
|
||||
keymapper::bind_for(name, newcommand);
|
||||
} catch(std::exception& e) {
|
||||
fault = true;
|
||||
faulttext = e.what();
|
||||
}
|
||||
});
|
||||
if(fault)
|
||||
wxMessageBox(wxT("Error"), towxstring("Can't bind key: " + faulttext), wxICON_EXCLAMATION);
|
||||
refresh();
|
||||
try {
|
||||
keymapper::bind_for(name, newcommand);
|
||||
} catch(std::exception& e) {
|
||||
wxMessageBox(wxT("Error"), towxstring(std::string("Can't bind key: ") + e.what()),
|
||||
wxICON_EXCLAMATION);
|
||||
}
|
||||
} catch(...) {
|
||||
refresh();
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
|
||||
void wxeditor_esettings_bindings::on_edit(wxCommandEvent& e)
|
||||
|
@ -1309,26 +1288,18 @@ void wxeditor_esettings_bindings::on_edit(wxCommandEvent& e)
|
|||
return;
|
||||
}
|
||||
try {
|
||||
std::string old_command_value;
|
||||
runemufn([&old_command_value, name]() { old_command_value = keymapper::get_command_for(name); });
|
||||
std::string old_command_value = keymapper::get_command_for(name);
|
||||
std::string newcommand = pick_text(this, "Edit binding", "Enter new command for binding:",
|
||||
old_command_value);
|
||||
bool fault = false;
|
||||
std::string faulttext;
|
||||
runemufn([&fault, &faulttext, name, newcommand]() {
|
||||
try {
|
||||
keymapper::bind_for(name, newcommand);
|
||||
} catch(std::exception& e) {
|
||||
fault = true;
|
||||
faulttext = e.what();
|
||||
}
|
||||
});
|
||||
if(fault)
|
||||
wxMessageBox(wxT("Error"), towxstring("Can't bind key: " + faulttext), wxICON_EXCLAMATION);
|
||||
refresh();
|
||||
try {
|
||||
keymapper::bind_for(name, newcommand);
|
||||
} catch(std::exception& e) {
|
||||
wxMessageBox(wxT("Error"), towxstring(std::string("Can't bind key: ") + e.what()),
|
||||
wxICON_EXCLAMATION);
|
||||
}
|
||||
} catch(...) {
|
||||
refresh();
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
|
||||
void wxeditor_esettings_bindings::on_delete(wxCommandEvent& e)
|
||||
|
@ -1338,7 +1309,7 @@ void wxeditor_esettings_bindings::on_delete(wxCommandEvent& e)
|
|||
refresh();
|
||||
return;
|
||||
}
|
||||
runemufn([name]() { try { keymapper::bind_for(name, ""); } catch(...) {} });
|
||||
try { keymapper::bind_for(name, ""); } catch(...) {}
|
||||
refresh();
|
||||
}
|
||||
|
||||
|
@ -1347,11 +1318,9 @@ void wxeditor_esettings_bindings::refresh()
|
|||
int n = select->GetSelection();
|
||||
std::map<std::string, std::string> bind;
|
||||
std::vector<wxString> choices;
|
||||
runemufn([&bind]() {
|
||||
std::set<std::string> a = keymapper::get_bindings();
|
||||
for(auto i : a)
|
||||
bind[i] = keymapper::get_command_for(i);
|
||||
});
|
||||
std::set<std::string> a = keymapper::get_bindings();
|
||||
for(auto i : a)
|
||||
bind[i] = keymapper::get_command_for(i);
|
||||
for(auto i : bind) {
|
||||
numbers[choices.size()] = i.first;
|
||||
choices.push_back(towxstring(i.first + " (" + i.second + ")"));
|
||||
|
|
|
@ -11,6 +11,18 @@ struct wxw_mutex : public mutex
|
|||
wxMutex* m;
|
||||
};
|
||||
|
||||
struct wxw_rec_mutex : public mutex
|
||||
{
|
||||
wxw_rec_mutex() throw(std::bad_alloc);
|
||||
~wxw_rec_mutex() throw();
|
||||
void lock() throw();
|
||||
void unlock() throw();
|
||||
wxMutex* m;
|
||||
volatile bool locked;
|
||||
uint32_t owner;
|
||||
uint32_t count;
|
||||
};
|
||||
|
||||
wxw_mutex::wxw_mutex() throw(std::bad_alloc)
|
||||
{
|
||||
m = new wxMutex();
|
||||
|
@ -31,11 +43,55 @@ void wxw_mutex::unlock() throw()
|
|||
m->Unlock();
|
||||
}
|
||||
|
||||
wxw_rec_mutex::wxw_rec_mutex() throw(std::bad_alloc)
|
||||
{
|
||||
m = new wxMutex();
|
||||
locked = false;
|
||||
owner = 0;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
wxw_rec_mutex::~wxw_rec_mutex() throw()
|
||||
{
|
||||
delete m;
|
||||
}
|
||||
|
||||
void wxw_rec_mutex::lock() throw()
|
||||
{
|
||||
uint32_t our_id = wxThread::GetCurrentId();
|
||||
if(locked && owner == our_id) {
|
||||
//Owned by us, increment lock count.
|
||||
++count;
|
||||
return;
|
||||
}
|
||||
m->Lock();
|
||||
locked = true;
|
||||
owner = our_id;
|
||||
count = 1;
|
||||
}
|
||||
|
||||
void wxw_rec_mutex::unlock() throw()
|
||||
{
|
||||
uint32_t our_id = wxThread::GetCurrentId();
|
||||
if(!locked || owner != our_id)
|
||||
std::cerr << "Warning: Trying to unlock recursive lock locked by another thread!" << std::endl;
|
||||
if(!--count) {
|
||||
locked = false;
|
||||
owner = 0;
|
||||
m->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
mutex& mutex::aquire() throw(std::bad_alloc)
|
||||
{
|
||||
return *new wxw_mutex;
|
||||
}
|
||||
|
||||
mutex& mutex::aquire_rec() throw(std::bad_alloc)
|
||||
{
|
||||
return *new wxw_rec_mutex;
|
||||
}
|
||||
|
||||
struct wxw_condition : public condition
|
||||
{
|
||||
wxw_condition(mutex& m) throw(std::bad_alloc);
|
||||
|
|
Loading…
Add table
Reference in a new issue