mirror of
https://github.com/love2d/love.git
synced 2026-08-16 00:02:12 +02:00
Switch to a custom event system, where SDL pumps into
To do this we needed to take ThreadVariant out of love.thread, and move it to common. This also changes event names, instead of 1/2-letter abbreviations, full names!
This commit is contained in:
+51
-18
@@ -24,18 +24,65 @@ namespace love
|
||||
{
|
||||
namespace event
|
||||
{
|
||||
Message::Message(std::string name, int nargs, ...)
|
||||
: name(name), nargs(nargs)
|
||||
{
|
||||
args = new Variant*[nargs];
|
||||
va_list arg;
|
||||
va_start(arg, nargs);
|
||||
for (int i = 0; i < nargs; i++)
|
||||
{
|
||||
args[i] = va_arg(arg, Variant*);
|
||||
args[i]->retain();
|
||||
}
|
||||
va_end(arg);
|
||||
}
|
||||
|
||||
Message::~Message()
|
||||
{
|
||||
for (int i = 0; i < nargs; i++)
|
||||
args[i]->release();
|
||||
}
|
||||
|
||||
int Message::toLua(lua_State *L)
|
||||
{
|
||||
lua_pushstring(L, name.c_str());
|
||||
for (int i = 0; i < nargs; i++)
|
||||
args[i]->toLua(L);
|
||||
return nargs+1;
|
||||
}
|
||||
|
||||
Message *Message::fromLua(lua_State *L, int n)
|
||||
{
|
||||
std::string name = luaL_checkstring(L, n);
|
||||
Message *m = new Message(name, 0);
|
||||
int nargs = lua_gettop(L)-n;
|
||||
delete[] m->args;
|
||||
m->args = new Variant*[nargs];
|
||||
for (int i = 0; i < nargs; i++)
|
||||
{
|
||||
m->args[i] = Variant::fromLua(L, n+i);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
Event::~Event()
|
||||
{
|
||||
}
|
||||
|
||||
bool Event::getConstant(const char * in, Event::Type & out)
|
||||
void Event::push(Message *msg)
|
||||
{
|
||||
return types.find(in, out);
|
||||
msg->retain();
|
||||
queue.push(msg);
|
||||
}
|
||||
|
||||
bool Event::getConstant(Event::Type in, const char *& out)
|
||||
bool Event::poll(Message *&msg)
|
||||
{
|
||||
return types.find(in, out);
|
||||
if (queue.empty())
|
||||
return false;
|
||||
msg = queue.front();
|
||||
queue.pop();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Event::getConstant(const char * in, love::mouse::Mouse::Button & out)
|
||||
@@ -58,20 +105,6 @@ namespace event
|
||||
return keys.find(in, out);
|
||||
}
|
||||
|
||||
StringMap<Event::Type, Event::TYPE_MAX_ENUM>::Entry Event::typeEntries[] =
|
||||
{
|
||||
{"kp", Event::TYPE_KEY_PRESSED},
|
||||
{"kr", Event::TYPE_KEY_RELEASED},
|
||||
{"mp", Event::TYPE_MOUSE_PRESSED},
|
||||
{"mr", Event::TYPE_MOUSE_RELEASED},
|
||||
{"jp", Event::TYPE_JOYSTICK_PRESSED},
|
||||
{"jr", Event::TYPE_JOYSTICK_RELEASED},
|
||||
{"f", Event::TYPE_FOCUS},
|
||||
{"q", Event::TYPE_QUIT},
|
||||
};
|
||||
|
||||
StringMap<Event::Type, Event::TYPE_MAX_ENUM> Event::types(Event::typeEntries, sizeof(Event::typeEntries));
|
||||
|
||||
StringMap<love::mouse::Mouse::Button, love::mouse::Mouse::BUTTON_MAX_ENUM>::Entry Event::buttonEntries[] =
|
||||
{
|
||||
{"l", love::mouse::Mouse::BUTTON_LEFT},
|
||||
|
||||
+26
-54
@@ -24,77 +24,49 @@
|
||||
// LOVE
|
||||
#include <common/Module.h>
|
||||
#include <common/StringMap.h>
|
||||
#include <common/Variant.h>
|
||||
#include <keyboard/Keyboard.h>
|
||||
#include <mouse/Mouse.h>
|
||||
|
||||
// STL
|
||||
#include <queue>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace event
|
||||
{
|
||||
class Message : public Object
|
||||
{
|
||||
private:
|
||||
std::string name;
|
||||
Variant **args;
|
||||
int nargs;
|
||||
|
||||
public:
|
||||
Message(std::string name, int nargs, ...);
|
||||
~Message();
|
||||
|
||||
int toLua(lua_State *L);
|
||||
static Message *fromLua(lua_State *L, int n);
|
||||
};
|
||||
|
||||
class Event : public Module
|
||||
{
|
||||
public:
|
||||
|
||||
enum Type
|
||||
{
|
||||
TYPE_INVALID,
|
||||
TYPE_KEY_PRESSED,
|
||||
TYPE_KEY_RELEASED,
|
||||
TYPE_MOUSE_PRESSED,
|
||||
TYPE_MOUSE_RELEASED,
|
||||
TYPE_JOYSTICK_RELEASED,
|
||||
TYPE_JOYSTICK_PRESSED,
|
||||
TYPE_FOCUS,
|
||||
TYPE_QUIT,
|
||||
TYPE_MAX_ENUM = 32
|
||||
};
|
||||
|
||||
union Message
|
||||
{
|
||||
Type type;
|
||||
|
||||
struct
|
||||
{
|
||||
Type type;
|
||||
love::mouse::Mouse::Button b;
|
||||
unsigned x;
|
||||
unsigned y;
|
||||
} mouse;
|
||||
|
||||
struct
|
||||
{
|
||||
Type type;
|
||||
unsigned index;
|
||||
unsigned button;
|
||||
} joystick;
|
||||
|
||||
struct
|
||||
{
|
||||
Type type;
|
||||
love::keyboard::Keyboard::Key k;
|
||||
unsigned short u;
|
||||
} keyboard;
|
||||
|
||||
struct
|
||||
{
|
||||
Type type;
|
||||
bool f;
|
||||
} focus;
|
||||
};
|
||||
|
||||
virtual ~Event();
|
||||
|
||||
static bool getConstant(const char * in, Type & out);
|
||||
static bool getConstant(Type in, const char *& out);
|
||||
void push(Message *msg);
|
||||
bool poll(Message *&msg);
|
||||
|
||||
virtual void pump() = 0;
|
||||
|
||||
static bool getConstant(const char * in, love::mouse::Mouse::Button & out);
|
||||
static bool getConstant(love::mouse::Mouse::Button in, const char *& out);
|
||||
static bool getConstant(const char * in, love::keyboard::Keyboard::Key & out);
|
||||
static bool getConstant(love::keyboard::Keyboard::Key in, const char *& out);
|
||||
|
||||
private:
|
||||
|
||||
static StringMap<Type, TYPE_MAX_ENUM>::Entry typeEntries[];
|
||||
static StringMap<Type, TYPE_MAX_ENUM> types;
|
||||
protected:
|
||||
std::queue<Message*> queue;
|
||||
static StringMap<love::mouse::Mouse::Button, love::mouse::Mouse::BUTTON_MAX_ENUM>::Entry buttonEntries[];
|
||||
static StringMap<love::mouse::Mouse::Button, love::mouse::Mouse::BUTTON_MAX_ENUM> buttons;
|
||||
static StringMap<love::keyboard::Keyboard::Key, love::keyboard::Keyboard::KEY_MAX_ENUM>::Entry keyEntries[];
|
||||
|
||||
@@ -42,35 +42,30 @@ namespace sdl
|
||||
void Event::pump()
|
||||
{
|
||||
SDL_PumpEvents();
|
||||
}
|
||||
|
||||
bool Event::poll(Message & message)
|
||||
{
|
||||
static SDL_Event e;
|
||||
|
||||
SDL_EnableUNICODE(1);
|
||||
|
||||
Message *msg;
|
||||
|
||||
while (SDL_PollEvent(&e))
|
||||
{
|
||||
if (convert(e, message))
|
||||
return true;
|
||||
msg = convert(e);
|
||||
if (msg)
|
||||
{
|
||||
push(msg);
|
||||
msg->release();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Event::wait(Message & message)
|
||||
Message *Event::wait()
|
||||
{
|
||||
static SDL_Event e;
|
||||
bool ok = (SDL_WaitEvent(&e) == 1);
|
||||
return ok && convert(e, message);
|
||||
}
|
||||
|
||||
bool Event::push(Message & message)
|
||||
{
|
||||
static SDL_Event e;
|
||||
bool ok = convert(message, e);
|
||||
return ok && (SDL_PushEvent(&e) == 0);
|
||||
if (!ok)
|
||||
return NULL;
|
||||
return convert(e);
|
||||
}
|
||||
|
||||
void Event::clear()
|
||||
@@ -81,83 +76,78 @@ namespace sdl
|
||||
{
|
||||
// Do nothing with 'e' ...
|
||||
}
|
||||
|
||||
while (!queue.empty())
|
||||
{
|
||||
queue.back()->release();
|
||||
queue.pop();
|
||||
}
|
||||
}
|
||||
|
||||
bool Event::convert(SDL_Event & e, Message & m)
|
||||
Message *Event::convert(SDL_Event & e)
|
||||
{
|
||||
Message *msg = NULL;
|
||||
love::keyboard::Keyboard::Key key;
|
||||
love::mouse::Mouse::Button button;
|
||||
Variant *arg1, *arg2, *arg3;
|
||||
const char *txt;
|
||||
switch(e.type)
|
||||
{
|
||||
case SDL_KEYDOWN:
|
||||
m.type = Event::TYPE_KEY_PRESSED;
|
||||
m.keyboard.u = e.key.keysym.unicode;
|
||||
return keys.find(e.key.keysym.sym, m.keyboard.k);
|
||||
if (keys.find(e.key.keysym.sym, key) && love::event::Event::keys.find(key, txt))
|
||||
{
|
||||
arg1 = new Variant(txt, strlen(txt));
|
||||
arg2 = new Variant((double) e.key.keysym.unicode);
|
||||
msg = new Message("keypressed", 2, arg1, arg2);
|
||||
arg1->release();
|
||||
arg2->release();
|
||||
}
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
m.type = Event::TYPE_KEY_RELEASED;
|
||||
return keys.find(e.key.keysym.sym, m.keyboard.k);
|
||||
if (keys.find(e.key.keysym.sym, key) && love::event::Event::keys.find(key, txt))
|
||||
{
|
||||
arg1 = new Variant(txt, strlen(txt));
|
||||
msg = new Message("keyreleased", 1, arg1);
|
||||
arg1->release();
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
m.type = (e.type == SDL_MOUSEBUTTONDOWN) ? Event::TYPE_MOUSE_PRESSED : Event::TYPE_MOUSE_RELEASED;
|
||||
m.mouse.x = e.button.x;
|
||||
m.mouse.y = e.button.y;
|
||||
return buttons.find(e.button.button, m.mouse.b);
|
||||
if (buttons.find(e.button.button, button) && love::event::Event::buttons.find(button, txt))
|
||||
{
|
||||
arg1 = new Variant((double) e.button.x);
|
||||
arg2 = new Variant((double) e.button.y);
|
||||
arg3 = new Variant(txt, strlen(txt));
|
||||
msg = new Message((e.type == SDL_MOUSEBUTTONDOWN) ?
|
||||
"mousepressed" : "mousereleased", 3,
|
||||
arg1, arg2, arg3);
|
||||
arg1->release();
|
||||
arg2->release();
|
||||
arg3->release();
|
||||
}
|
||||
break;
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
case SDL_JOYBUTTONUP:
|
||||
m.type = (e.type == SDL_JOYBUTTONDOWN) ? Event::TYPE_JOYSTICK_PRESSED : Event::TYPE_JOYSTICK_RELEASED;
|
||||
m.joystick.button = e.jbutton.button;
|
||||
m.joystick.index = e.jbutton.which;
|
||||
return true;
|
||||
arg1 = new Variant((double) (e.jbutton.which+1));
|
||||
arg2 = new Variant((double) (e.jbutton.button+1));
|
||||
msg = new Message((e.type == SDL_JOYBUTTONDOWN) ?
|
||||
"joystickpressed" : "joystickreleased", 2,
|
||||
arg1, arg2);
|
||||
arg1->release();
|
||||
arg2->release();
|
||||
break;
|
||||
case SDL_ACTIVEEVENT:
|
||||
arg1 = new Variant(e.active.gain != 0);
|
||||
if (e.active.state & SDL_APPINPUTFOCUS)
|
||||
{
|
||||
m.type = Event::TYPE_FOCUS;
|
||||
m.focus.f = (e.active.gain != 0);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
break;
|
||||
msg = new Message("focus", 1, arg1);
|
||||
arg1->release();
|
||||
break;
|
||||
case SDL_QUIT:
|
||||
m.type = Event::TYPE_QUIT;
|
||||
return true;
|
||||
msg = new Message("quit", 0);
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Event::convert(Message & m, SDL_Event & e)
|
||||
{
|
||||
switch(m.type)
|
||||
{
|
||||
case Event::TYPE_KEY_PRESSED:
|
||||
e.type = SDL_KEYDOWN;
|
||||
e.key.keysym.unicode = (Uint16)m.keyboard.u;
|
||||
return keys.find(m.keyboard.k, e.key.keysym.sym);
|
||||
case Event::TYPE_KEY_RELEASED:
|
||||
e.type = SDL_KEYUP;
|
||||
return keys.find(m.keyboard.k, e.key.keysym.sym);
|
||||
case Event::TYPE_MOUSE_PRESSED:
|
||||
case Event::TYPE_MOUSE_RELEASED:
|
||||
e.type = (m.type == Event::TYPE_MOUSE_PRESSED) ? SDL_MOUSEBUTTONDOWN : SDL_MOUSEBUTTONUP;
|
||||
e.button.x = m.mouse.x;
|
||||
e.button.y = m.mouse.y;
|
||||
return buttons.find(m.mouse.b, e.button.button);
|
||||
case Event::TYPE_JOYSTICK_PRESSED:
|
||||
case Event::TYPE_JOYSTICK_RELEASED:
|
||||
e.type = (m.type == Event::TYPE_JOYSTICK_PRESSED) ? SDL_JOYBUTTONDOWN : SDL_JOYBUTTONUP;
|
||||
e.jbutton.which = m.joystick.index;
|
||||
e.jbutton.button = m.joystick.button;
|
||||
return true;
|
||||
case Event::TYPE_FOCUS:
|
||||
e.type = SDL_ACTIVEEVENT;
|
||||
e.active.state = SDL_APPINPUTFOCUS;
|
||||
e.active.gain = m.focus.f;
|
||||
case Event::TYPE_QUIT:
|
||||
e.type = SDL_QUIT;
|
||||
return true;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
return msg;
|
||||
}
|
||||
|
||||
EnumMap<love::keyboard::Keyboard::Key, SDLKey, love::keyboard::Keyboard::KEY_MAX_ENUM>::Entry Event::keyEntries[] =
|
||||
|
||||
@@ -51,28 +51,12 @@ namespace sdl
|
||||
**/
|
||||
void pump();
|
||||
|
||||
/**
|
||||
* Checks if there are messages in the queue.
|
||||
*
|
||||
* @param message The next message in the queue, if the return value is true.
|
||||
* @return True if there a message was found, false otherwise.
|
||||
**/
|
||||
bool poll(Message & message);
|
||||
|
||||
/**
|
||||
* Waits for the next event (indefinitely). Useful for creating games where
|
||||
* the screen and game state only needs updating when the user interacts with
|
||||
* the window.
|
||||
**/
|
||||
bool wait(Message & message);
|
||||
|
||||
/**
|
||||
* Push a message onto the event queue.
|
||||
*
|
||||
* @param message The message to push onto the queue.
|
||||
* @return True on success, false if the queue was full.
|
||||
**/
|
||||
bool push(Message & message);
|
||||
Message *wait();
|
||||
|
||||
/**
|
||||
* Clears the event queue.
|
||||
@@ -81,8 +65,7 @@ namespace sdl
|
||||
|
||||
private:
|
||||
|
||||
bool convert(SDL_Event & e, Message & m);
|
||||
bool convert(Message & m, SDL_Event & e);
|
||||
Message *convert(SDL_Event & e);
|
||||
|
||||
static EnumMap<love::keyboard::Keyboard::Key, SDLKey, love::keyboard::Keyboard::KEY_MAX_ENUM>::Entry keyEntries[];
|
||||
static EnumMap<love::keyboard::Keyboard::Key, SDLKey, love::keyboard::Keyboard::KEY_MAX_ENUM> keys;
|
||||
|
||||
@@ -34,104 +34,15 @@ namespace sdl
|
||||
{
|
||||
static Event * instance = 0;
|
||||
|
||||
static bool to_message(lua_State * L, Event::Message & msg)
|
||||
{
|
||||
const char * str = luaL_checkstring(L, 1);
|
||||
|
||||
if (!Event::getConstant(str, msg.type))
|
||||
return false;
|
||||
|
||||
switch(msg.type)
|
||||
{
|
||||
case Event::TYPE_KEY_PRESSED:
|
||||
if (!Event::getConstant(luaL_checkstring(L, 2), msg.keyboard.k))
|
||||
return false;
|
||||
msg.keyboard.u = (unsigned short)luaL_optint(L, 3, 0);
|
||||
return true;
|
||||
case Event::TYPE_KEY_RELEASED:
|
||||
if (!Event::getConstant(luaL_checkstring(L, 2), msg.keyboard.k))
|
||||
return false;
|
||||
return true;
|
||||
case Event::TYPE_MOUSE_PRESSED:
|
||||
case Event::TYPE_MOUSE_RELEASED:
|
||||
if (!Event::getConstant(luaL_checkstring(L, 2), msg.mouse.b))
|
||||
return false;
|
||||
msg.mouse.x = luaL_checkint(L, 3);
|
||||
msg.mouse.y = luaL_checkint(L, 4);
|
||||
return true;
|
||||
case Event::TYPE_JOYSTICK_PRESSED:
|
||||
case Event::TYPE_JOYSTICK_RELEASED:
|
||||
msg.joystick.index = luaL_checkint(L, 2);
|
||||
msg.joystick.button = luaL_checkint(L, 3);
|
||||
return true;
|
||||
case Event::TYPE_FOCUS:
|
||||
msg.focus.f = luax_toboolean(L, 2);
|
||||
return true;
|
||||
case Event::TYPE_QUIT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int push_message(lua_State * L, const Event::Message & msg)
|
||||
{
|
||||
const char * str = 0;
|
||||
|
||||
if (!Event::getConstant(msg.type, str))
|
||||
return 0;
|
||||
|
||||
lua_pushstring(L, str);
|
||||
|
||||
switch(msg.type)
|
||||
{
|
||||
case Event::TYPE_KEY_PRESSED:
|
||||
if (!Event::getConstant(msg.keyboard.k, str))
|
||||
return 0;
|
||||
lua_pushstring(L, str);
|
||||
lua_pushinteger(L, msg.keyboard.u);
|
||||
return 3;
|
||||
case Event::TYPE_KEY_RELEASED:
|
||||
if (!Event::getConstant(msg.keyboard.k, str))
|
||||
return 0;
|
||||
lua_pushstring(L, str);
|
||||
return 2;
|
||||
case Event::TYPE_MOUSE_PRESSED:
|
||||
case Event::TYPE_MOUSE_RELEASED:
|
||||
if (!Event::getConstant(msg.mouse.b, str))
|
||||
return 0;
|
||||
lua_pushinteger(L, msg.mouse.x);
|
||||
lua_pushinteger(L, msg.mouse.y);
|
||||
lua_pushstring(L, str);
|
||||
return 4;
|
||||
case Event::TYPE_JOYSTICK_PRESSED:
|
||||
case Event::TYPE_JOYSTICK_RELEASED:
|
||||
lua_pushinteger(L, msg.joystick.index+1);
|
||||
lua_pushinteger(L, msg.joystick.button+1);
|
||||
return 3;
|
||||
case Event::TYPE_FOCUS:
|
||||
lua_pushboolean(L, msg.focus.f);
|
||||
return 2;
|
||||
case Event::TYPE_QUIT:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int poll_i(lua_State * L)
|
||||
{
|
||||
static Event::Message m;
|
||||
Message *m;
|
||||
|
||||
while (instance->poll(m))
|
||||
{
|
||||
int args = push_message(L, m);
|
||||
if (args > 0)
|
||||
return args;
|
||||
int args = m->toLua(L);
|
||||
m->release();
|
||||
return args;
|
||||
}
|
||||
|
||||
// No pending events.
|
||||
@@ -152,11 +63,13 @@ namespace sdl
|
||||
|
||||
int w_wait(lua_State * L)
|
||||
{
|
||||
static Event::Message m;
|
||||
static Message *m;
|
||||
|
||||
if (instance->wait(m))
|
||||
if ((m = instance->wait()))
|
||||
{
|
||||
return push_message(L, m);
|
||||
int args = m->toLua(L);
|
||||
m->release();
|
||||
return args;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -164,17 +77,18 @@ namespace sdl
|
||||
|
||||
int w_push(lua_State * L)
|
||||
{
|
||||
static Event::Message m;
|
||||
static Message *m;
|
||||
|
||||
if (!to_message(L, m))
|
||||
if (!(m = Message::fromLua(L, 1)))
|
||||
{
|
||||
luax_pushboolean(L, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
luax_pushboolean(L, instance->push(m));
|
||||
instance->push(m);
|
||||
m->release();
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_clear(lua_State *)
|
||||
@@ -185,9 +99,8 @@ namespace sdl
|
||||
|
||||
int w_quit(lua_State * L)
|
||||
{
|
||||
static Event::Message m;
|
||||
m.type = Event::TYPE_QUIT;
|
||||
luax_pushboolean(L, instance->push(m));
|
||||
Message *m = new Message("quit", 0);
|
||||
instance->push(m);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace thread
|
||||
{
|
||||
{
|
||||
Lock lock((Mutex*) comm->mutex);
|
||||
ThreadVariant *v = new ThreadVariant(lua_tostring(L, -1), lua_strlen(L, -1));
|
||||
Variant *v = new Variant(lua_tostring(L, -1), lua_strlen(L, -1));
|
||||
comm->setValue("error", v);
|
||||
v->release();
|
||||
}
|
||||
@@ -68,65 +68,6 @@ namespace thread
|
||||
lua_close(L);
|
||||
}
|
||||
|
||||
|
||||
ThreadVariant::ThreadVariant(bool boolean)
|
||||
{
|
||||
type = BOOLEAN;
|
||||
data.boolean = boolean;
|
||||
}
|
||||
|
||||
ThreadVariant::ThreadVariant(double number)
|
||||
{
|
||||
type = NUMBER;
|
||||
data.number = number;
|
||||
}
|
||||
|
||||
ThreadVariant::ThreadVariant(const char *string, size_t len)
|
||||
{
|
||||
type = STRING;
|
||||
char *buf = new char[len+1];
|
||||
memset(buf, 0, len+1);
|
||||
memcpy(buf, string, len);
|
||||
data.string.str = buf;
|
||||
data.string.len = len;
|
||||
}
|
||||
|
||||
ThreadVariant::ThreadVariant(void *userdata)
|
||||
{
|
||||
type = LUSERDATA;
|
||||
data.userdata = userdata;
|
||||
}
|
||||
|
||||
ThreadVariant::ThreadVariant(Type udatatype, void *userdata)
|
||||
{
|
||||
type = FUSERDATA;
|
||||
this->udatatype = udatatype;
|
||||
if (udatatype != INVALID_ID)
|
||||
{
|
||||
Proxy *p = (Proxy *) userdata;
|
||||
flags = p->flags;
|
||||
data.userdata = p->data;
|
||||
((love::Object *) data.userdata)->retain();
|
||||
}
|
||||
else
|
||||
data.userdata = userdata;
|
||||
}
|
||||
|
||||
ThreadVariant::~ThreadVariant()
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case STRING:
|
||||
delete[] data.string.str;
|
||||
break;
|
||||
case FUSERDATA:
|
||||
((love::Object *) data.userdata)->release();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ThreadData::ThreadData(const char *name, size_t len, const char *code, void *mutex, void *cond)
|
||||
: len(len), mutex(mutex), cond(cond)
|
||||
{
|
||||
@@ -162,7 +103,7 @@ namespace thread
|
||||
return name;
|
||||
}
|
||||
|
||||
ThreadVariant* ThreadData::getValue(const std::string & name)
|
||||
Variant* ThreadData::getValue(const std::string & name)
|
||||
{
|
||||
if (shared.count(name) == 0)
|
||||
return 0;
|
||||
@@ -177,7 +118,7 @@ namespace thread
|
||||
shared.erase(name);
|
||||
}
|
||||
|
||||
void ThreadData::setValue(const std::string & name, ThreadVariant *v)
|
||||
void ThreadData::setValue(const std::string & name, Variant *v)
|
||||
{
|
||||
if (shared.count(name) != 0)
|
||||
shared[name]->release();
|
||||
@@ -188,7 +129,7 @@ namespace thread
|
||||
std::vector<std::string> ThreadData::getKeys()
|
||||
{
|
||||
std::vector<std::string> keys;
|
||||
for (std::map<std::string, ThreadVariant*>::iterator it = shared.begin(); it != shared.end(); it++)
|
||||
for (std::map<std::string, Variant*>::iterator it = shared.begin(); it != shared.end(); it++)
|
||||
{
|
||||
keys.push_back(it->first);
|
||||
}
|
||||
@@ -273,9 +214,9 @@ namespace thread
|
||||
return name;
|
||||
}
|
||||
|
||||
ThreadVariant *Thread::get(const std::string & name)
|
||||
Variant *Thread::get(const std::string & name)
|
||||
{
|
||||
ThreadVariant *v = comm->getValue(name);
|
||||
Variant *v = comm->getValue(name);
|
||||
if (v)
|
||||
v->retain();
|
||||
return v;
|
||||
@@ -286,9 +227,9 @@ namespace thread
|
||||
return comm->getKeys();
|
||||
}
|
||||
|
||||
ThreadVariant *Thread::demand(const std::string & name)
|
||||
Variant *Thread::demand(const std::string & name)
|
||||
{
|
||||
ThreadVariant *v = comm->getValue(name);
|
||||
Variant *v = comm->getValue(name);
|
||||
while (!v)
|
||||
{
|
||||
if (comm->getValue("error"))
|
||||
@@ -305,7 +246,7 @@ namespace thread
|
||||
comm->clearValue(name);
|
||||
}
|
||||
|
||||
void Thread::set(const std::string & name, ThreadVariant *v)
|
||||
void Thread::set(const std::string & name, Variant *v)
|
||||
{
|
||||
lock(); //this function explicitly locks
|
||||
comm->setValue(name, v); //because we need
|
||||
|
||||
@@ -31,9 +31,9 @@
|
||||
#include <filesystem/File.h>
|
||||
#include <common/runtime.h>
|
||||
#include <common/Module.h>
|
||||
#include <common/Variant.h>
|
||||
#include <thread/threads.h>
|
||||
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace thread
|
||||
@@ -41,46 +41,12 @@ namespace thread
|
||||
|
||||
class ThreadModule;
|
||||
|
||||
enum ThreadVariantType
|
||||
{
|
||||
UNKNOWN = 0,
|
||||
BOOLEAN,
|
||||
NUMBER,
|
||||
STRING,
|
||||
LUSERDATA,
|
||||
FUSERDATA
|
||||
};
|
||||
|
||||
class ThreadVariant : public love::Object
|
||||
{
|
||||
public:
|
||||
ThreadVariant(bool boolean);
|
||||
ThreadVariant(double number);
|
||||
ThreadVariant(const char *string, size_t len);
|
||||
ThreadVariant(void *userdata);
|
||||
ThreadVariant(Type udatatype, void *userdata);
|
||||
virtual ~ThreadVariant();
|
||||
ThreadVariantType type;
|
||||
union
|
||||
{
|
||||
bool boolean;
|
||||
double number;
|
||||
struct {
|
||||
const char *str;
|
||||
size_t len;
|
||||
} string;
|
||||
void *userdata;
|
||||
} data;
|
||||
Type udatatype;
|
||||
bits flags;
|
||||
};
|
||||
|
||||
class ThreadData
|
||||
{
|
||||
private:
|
||||
char *code;
|
||||
char *name;
|
||||
std::map<std::string, ThreadVariant*> shared;
|
||||
std::map<std::string, Variant*> shared;
|
||||
size_t len;
|
||||
|
||||
public:
|
||||
@@ -88,9 +54,9 @@ namespace thread
|
||||
~ThreadData();
|
||||
const char *getCode();
|
||||
const char *getName(size_t *len = 0);
|
||||
ThreadVariant* getValue(const std::string & name);
|
||||
Variant* getValue(const std::string & name);
|
||||
void clearValue(const std::string & name);
|
||||
void setValue(const std::string & name, ThreadVariant *v);
|
||||
void setValue(const std::string & name, Variant *v);
|
||||
std::vector<std::string> getKeys();
|
||||
|
||||
void *mutex;
|
||||
@@ -130,11 +96,11 @@ namespace thread
|
||||
void kill();
|
||||
void wait();
|
||||
std::string getName();
|
||||
ThreadVariant *get(const std::string & name);
|
||||
Variant *get(const std::string & name);
|
||||
std::vector<std::string> getKeys();
|
||||
ThreadVariant *demand(const std::string & name);
|
||||
Variant *demand(const std::string & name);
|
||||
void clear(const std::string & name);
|
||||
void set(const std::string & name, ThreadVariant *v);
|
||||
void set(const std::string & name, Variant *v);
|
||||
void lock();
|
||||
void unlock();
|
||||
}; // Thread
|
||||
|
||||
@@ -58,58 +58,21 @@ namespace thread
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool __pushThreadVariant(lua_State *L, ThreadVariant *v)
|
||||
{
|
||||
if (!v)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
return false;
|
||||
}
|
||||
switch(v->type)
|
||||
{
|
||||
case BOOLEAN:
|
||||
lua_pushboolean(L, v->data.boolean);
|
||||
break;
|
||||
case NUMBER:
|
||||
lua_pushnumber(L, v->data.number);
|
||||
break;
|
||||
case STRING:
|
||||
lua_pushlstring(L, v->data.string.str, v->data.string.len);
|
||||
break;
|
||||
case LUSERDATA:
|
||||
lua_pushlightuserdata(L, v->data.userdata);
|
||||
break;
|
||||
case FUSERDATA:
|
||||
if (v->udatatype != INVALID_ID)
|
||||
{
|
||||
const char *name = NULL;
|
||||
love::types.find(v->udatatype, name);
|
||||
((love::Object *) v->data.userdata)->retain();
|
||||
luax_newtype(L, name, v->flags, v->data.userdata);
|
||||
}
|
||||
else
|
||||
lua_pushlightuserdata(L, v->data.userdata);
|
||||
// I know this is not the same
|
||||
// sadly, however, it's the most
|
||||
// I can do (at the moment).
|
||||
break;
|
||||
default:
|
||||
lua_pushnil(L);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int w_Thread_get(lua_State *L)
|
||||
{
|
||||
Thread *t = luax_checkthread(L, 1);
|
||||
std::string name = luax_checkstring(L, 2);
|
||||
t->lock();
|
||||
ThreadVariant *v = t->get(name);
|
||||
Variant *v = t->get(name);
|
||||
t->clear(name);
|
||||
t->unlock();
|
||||
if (!__pushThreadVariant(L, v))
|
||||
if (!v)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
v->toLua(L);
|
||||
t->lock();
|
||||
v->release();
|
||||
t->unlock();
|
||||
@@ -138,11 +101,15 @@ namespace thread
|
||||
Thread *t = luax_checkthread(L, 1);
|
||||
std::string name = luax_checkstring(L, 2);
|
||||
t->lock();
|
||||
ThreadVariant *v = t->demand(name);
|
||||
Variant *v = t->demand(name);
|
||||
t->clear(name);
|
||||
t->unlock();
|
||||
if (!__pushThreadVariant(L, v))
|
||||
if (!v)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
v->toLua(L);
|
||||
t->lock();
|
||||
v->release();
|
||||
t->unlock();
|
||||
@@ -154,60 +121,28 @@ namespace thread
|
||||
Thread *t = luax_checkthread(L, 1);
|
||||
std::string name = luax_checkstring(L, 2);
|
||||
t->lock();
|
||||
ThreadVariant *v = t->get(name);
|
||||
Variant *v = t->get(name);
|
||||
t->unlock();
|
||||
if (!__pushThreadVariant(L, v))
|
||||
if (!v)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
v->toLua(L);
|
||||
t->lock();
|
||||
v->release();
|
||||
t->unlock();
|
||||
return 1;
|
||||
}
|
||||
|
||||
Type extractudatatype(lua_State * L, int idx)
|
||||
{
|
||||
Type t = INVALID_ID;
|
||||
if (!lua_isuserdata(L, idx))
|
||||
return t;
|
||||
if (luaL_getmetafield (L, idx, "__tostring") == 0)
|
||||
return t;
|
||||
lua_pushvalue(L, idx);
|
||||
int result = lua_pcall(L, 1, 1, 0);
|
||||
if (result == 0)
|
||||
types.find(lua_tostring(L, -1), t);
|
||||
if (result == 0 || result == LUA_ERRRUN)
|
||||
lua_pop(L, 1);
|
||||
return t;
|
||||
}
|
||||
|
||||
int w_Thread_set(lua_State *L)
|
||||
{
|
||||
Thread *t = luax_checkthread(L, 1);
|
||||
std::string name = luax_checkstring(L, 2);
|
||||
ThreadVariant *v;
|
||||
size_t len;
|
||||
const char *str;
|
||||
switch(lua_type(L, 3))
|
||||
{
|
||||
case LUA_TBOOLEAN:
|
||||
v = new ThreadVariant(luax_toboolean(L, 3));
|
||||
break;
|
||||
case LUA_TNUMBER:
|
||||
v = new ThreadVariant(lua_tonumber(L, 3));
|
||||
break;
|
||||
case LUA_TSTRING:
|
||||
str = lua_tolstring(L, 3, &len);
|
||||
v = new ThreadVariant(str, len);
|
||||
break;
|
||||
case LUA_TLIGHTUSERDATA:
|
||||
v = new ThreadVariant(lua_touserdata(L, 3));
|
||||
break;
|
||||
case LUA_TUSERDATA:
|
||||
v = new ThreadVariant(extractudatatype(L, 3), lua_touserdata(L, 3));
|
||||
break;
|
||||
default:
|
||||
return luaL_error(L, "Expected boolean, number, string or userdata");
|
||||
}
|
||||
Variant *v = Variant::fromLua(L, 3);
|
||||
if (!v)
|
||||
return luaL_error(L, "Expected boolean, number, string or userdata");
|
||||
t->set(name, v);
|
||||
t->lock();
|
||||
v->release();
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
|
||||
namespace love
|
||||
{
|
||||
extern StringMap<Type, TYPE_MAX_ENUM> types;
|
||||
namespace thread
|
||||
{
|
||||
Thread *luax_checkthread(lua_State *L, int idx);
|
||||
|
||||
Reference in New Issue
Block a user