mirror of
https://github.com/tuxbox-neutrino/neutrino.git
synced 2025-08-29 16:31:11 +02:00
CLuaInstance: Add linux pthread support
- code ported from lua-llthreads2 (https://github.com/moteus/lua-llthreads2) - code in neutrino integrated for use of lua neutrino api in threads - add thread::cancel() function - Set Lua api version to 1.34
This commit is contained in:
@@ -41,4 +41,7 @@ libneutrino_gui_lua_a_SOURCES = \
|
|||||||
lua_menue.cpp \
|
lua_menue.cpp \
|
||||||
lua_messagebox.cpp \
|
lua_messagebox.cpp \
|
||||||
lua_misc.cpp \
|
lua_misc.cpp \
|
||||||
|
lua_threads.cpp \
|
||||||
|
lua_threads_copy.cpp \
|
||||||
|
lua_threads_functions.cpp \
|
||||||
lua_video.cpp
|
lua_video.cpp
|
||||||
|
391
src/gui/lua/lua_threads.cpp
Normal file
391
src/gui/lua/lua_threads.cpp
Normal file
@@ -0,0 +1,391 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Copyright (c) 2011 by Robert G. Jakabosky <bobby@sharedrealm.com>
|
||||||
|
* Copyright (c) 2015 M. Liebmann (micha-bbg)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <memory.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include <driver/rcinput.h>
|
||||||
|
#include <gui/lua/luainstance.h>
|
||||||
|
#include "lua_threads.h"
|
||||||
|
|
||||||
|
int __strerror_r(int err, char* buf, size_t len)
|
||||||
|
{
|
||||||
|
memset(buf, '\0', len);
|
||||||
|
snprintf(buf, len-1, "%s", strerror(err));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLLThread* CLLThread::getInstance()
|
||||||
|
{
|
||||||
|
static CLLThread* llthreadInst = NULL;
|
||||||
|
|
||||||
|
if (!llthreadInst)
|
||||||
|
llthreadInst = new CLLThread();
|
||||||
|
return llthreadInst;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLLThread::llthread_log(lua_State *L, const char *hdr, const char *msg)
|
||||||
|
{
|
||||||
|
int top = lua_gettop(L);
|
||||||
|
lua_rawgetp(L, LUA_REGISTRYINDEX, LLTHREAD_LOGGER_HOLDER);
|
||||||
|
if (lua_isnil(L, -1)) {
|
||||||
|
lua_pop(L, 1);
|
||||||
|
fputs(hdr, stderr);
|
||||||
|
fputs(msg, stderr);
|
||||||
|
fputc('\n', stderr);
|
||||||
|
fflush(stderr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lua_pushstring(L, hdr);
|
||||||
|
lua_pushstring(L, msg);
|
||||||
|
lua_concat(L, 2);
|
||||||
|
lua_pcall(L, 1, 0, 0);
|
||||||
|
lua_settop(L, top);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLLThread::fail(lua_State *L, const char *msg)
|
||||||
|
{
|
||||||
|
lua_pushnil(L);
|
||||||
|
lua_pushstring(L, msg);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLLThread::traceback (lua_State *L)
|
||||||
|
{
|
||||||
|
const char *msg = lua_tostring(L, 1);
|
||||||
|
if (msg)
|
||||||
|
luaL_traceback(L, L, msg, 1);
|
||||||
|
else if (!lua_isnoneornil(L, 1)) { /* is there an error object? */
|
||||||
|
if (!luaL_callmeta(L, 1, "__tostring")) /* try its 'tostring' metamethod */
|
||||||
|
lua_pushliteral(L, "(no error message)");
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLLThread::open_thread_libs(lua_State *L)
|
||||||
|
{
|
||||||
|
/* Not yet tested calling thread from thread out */
|
||||||
|
/* LuaThreadsRegister(L); */
|
||||||
|
|
||||||
|
/* luainstance.cpp */
|
||||||
|
LuaInstRegisterFunctions(L, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
llthread_child_t *CLLThread::llthread_child_new()
|
||||||
|
{
|
||||||
|
llthread_child_t *_this = ALLOC_STRUCT(llthread_child_t);
|
||||||
|
if (!_this) return NULL;
|
||||||
|
|
||||||
|
memset(_this, 0, sizeof(llthread_child_t));
|
||||||
|
|
||||||
|
/* create new lua_State for the thread. */
|
||||||
|
/* open standard libraries. */
|
||||||
|
_this->L = luaL_newstate();
|
||||||
|
open_thread_libs(_this->L);
|
||||||
|
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
|
||||||
|
llthread_t *CLLThread::llthread_new()
|
||||||
|
{
|
||||||
|
llthread_t *_this = ALLOC_STRUCT(llthread_t);
|
||||||
|
if (!_this) return NULL;
|
||||||
|
|
||||||
|
_this->flags = FLAG_NONE;
|
||||||
|
_this->child = llthread_child_new();
|
||||||
|
if (!_this->child) {
|
||||||
|
FREE_STRUCT(_this);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLLThread::llthread_push_args(lua_State *L, llthread_child_t *child, int idx, int top)
|
||||||
|
{
|
||||||
|
return llthread_copy_values(L, child->L, idx, top, 1 /* is_arg */);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLLThread::llthread_push_results(lua_State *L, llthread_child_t *child, int idx, int top)
|
||||||
|
{
|
||||||
|
return llthread_copy_values(child->L, L, idx, top, 0 /* is_arg */);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLLThread::llthread_validate(llthread_t *_this)
|
||||||
|
{
|
||||||
|
/* describe valid state of llthread_t object
|
||||||
|
* from after create and before destroy
|
||||||
|
*/
|
||||||
|
if (!IS(_this, STARTED)) {
|
||||||
|
assert(!IS(_this, DETACHED));
|
||||||
|
assert(!IS(_this, JOINED));
|
||||||
|
assert(!IS(_this, JOINABLE));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS(_this, DETACHED)) {
|
||||||
|
if (!IS(_this, JOINABLE)) assert(_this->child == NULL);
|
||||||
|
else assert(_this->child != NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
llthread_t *CLLThread::llthread_create(lua_State *L, const char *code, size_t code_len)
|
||||||
|
{
|
||||||
|
llthread_t *_this = llthread_new();
|
||||||
|
llthread_child_t *child = _this->child;
|
||||||
|
|
||||||
|
/* load Lua code into child state. */
|
||||||
|
int rc = luaL_loadbuffer(child->L, code, code_len, code);
|
||||||
|
if (rc != 0) {
|
||||||
|
/* copy error message to parent state. */
|
||||||
|
size_t len; const char *str = lua_tolstring(child->L, -1, &len);
|
||||||
|
if (str != NULL) {
|
||||||
|
lua_pushlstring(L, str, len);
|
||||||
|
} else {
|
||||||
|
/* non-string error message. */
|
||||||
|
lua_pushfstring(L, "luaL_loadbuffer() failed to load Lua code: rc=%d", rc);
|
||||||
|
}
|
||||||
|
/* llthread_destroy(_this); */
|
||||||
|
lua_error(L);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy extra args from main state to child state. */
|
||||||
|
/* Push all args after the Lua code. */
|
||||||
|
llthread_push_args(L, child, 3, lua_gettop(L));
|
||||||
|
|
||||||
|
llthread_validate(_this);
|
||||||
|
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
|
||||||
|
llthread_t *CLLThread::l_llthread_at (lua_State *L, int i)
|
||||||
|
{
|
||||||
|
llthread_t **_this = (llthread_t **) luaL_checkudata(L, i, LLTHREAD_TAG);
|
||||||
|
return *_this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLLThread::llthread_child_destroy(llthread_child_t *_this)
|
||||||
|
{
|
||||||
|
lua_close(_this->L);
|
||||||
|
FREE_STRUCT(_this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLLThread::llthread_cleanup_child(llthread_t *_this)
|
||||||
|
{
|
||||||
|
if (_this->child) {
|
||||||
|
llthread_child_destroy(_this->child);
|
||||||
|
_this->child = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLLThread::llthread_detach(llthread_t *_this)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
assert(IS(_this, STARTED));
|
||||||
|
assert(_this->child != NULL);
|
||||||
|
|
||||||
|
_this->child = NULL;
|
||||||
|
|
||||||
|
/*we can not detach joined thread*/
|
||||||
|
if (IS(_this, JOINED))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
rc = pthread_detach(_this->thread);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* CLLThread::llthread_child_thread_run(void *arg)
|
||||||
|
{
|
||||||
|
llthread_child_t *_this = (llthread_child_t *)arg;
|
||||||
|
lua_State *L = _this->L;
|
||||||
|
int nargs = lua_gettop(L) - 1;
|
||||||
|
|
||||||
|
/* push traceback function as first value on stack. */
|
||||||
|
lua_pushcfunction(_this->L, traceback);
|
||||||
|
lua_insert(L, 1);
|
||||||
|
|
||||||
|
_this->status = lua_pcall(L, nargs, LUA_MULTRET, 1);
|
||||||
|
|
||||||
|
/* alwasy print errors here, helps with debugging bad code. */
|
||||||
|
if (_this->status != 0) {
|
||||||
|
llthread_log(L, "Error from thread: ", lua_tostring(L, -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS(_this, DETACHED) || !IS(_this, JOINABLE)) {
|
||||||
|
/* thread is detached, so it must clean-up the child state. */
|
||||||
|
llthread_child_destroy(_this);
|
||||||
|
_this = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLLThread::llthread_start(llthread_t *_this, int start_detached, int joinable)
|
||||||
|
{
|
||||||
|
llthread_child_t *child = _this->child;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
llthread_validate(_this);
|
||||||
|
|
||||||
|
if (joinable) SET(child, JOINABLE);
|
||||||
|
if (start_detached) SET(child, DETACHED);
|
||||||
|
|
||||||
|
rc = pthread_create(&(_this->thread), NULL, llthread_child_thread_run, child);
|
||||||
|
|
||||||
|
if (rc == 0) {
|
||||||
|
SET(_this, STARTED);
|
||||||
|
if (joinable) SET(_this, JOINABLE);
|
||||||
|
if (start_detached) SET(_this, DETACHED);
|
||||||
|
if ((start_detached)&&(!joinable)) {
|
||||||
|
rc = llthread_detach(_this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
llthread_validate(_this);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLLThread::llthread_cancel(llthread_t *_this)
|
||||||
|
{
|
||||||
|
llthread_validate(_this);
|
||||||
|
|
||||||
|
if (IS(_this, JOINED)) {
|
||||||
|
return JOIN_OK;
|
||||||
|
} else {
|
||||||
|
int rc = pthread_cancel(_this->thread);
|
||||||
|
if (rc == 0) {
|
||||||
|
return JOIN_ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc != ESRCH) {
|
||||||
|
/*@fixme what else it can be ?*/
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return JOIN_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLLThread::llthread_join(llthread_t *_this, join_timeout_t timeout)
|
||||||
|
{
|
||||||
|
llthread_validate(_this);
|
||||||
|
|
||||||
|
if (IS(_this, JOINED)) {
|
||||||
|
return JOIN_OK;
|
||||||
|
} else {
|
||||||
|
int rc;
|
||||||
|
if (timeout == 0) {
|
||||||
|
rc = pthread_kill(_this->thread, 0);
|
||||||
|
if (rc == 0) { /* still alive */
|
||||||
|
return JOIN_ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc != ESRCH) {
|
||||||
|
/*@fixme what else it can be ?*/
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*thread dead so we call join to free pthread_t struct */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @todo use pthread_tryjoin_np/pthread_timedjoin_np to support timeout */
|
||||||
|
|
||||||
|
/* then join the thread. */
|
||||||
|
rc = pthread_join(_this->thread, NULL);
|
||||||
|
if ((rc == 0) || (rc == ESRCH)) {
|
||||||
|
SET(_this, JOINED);
|
||||||
|
rc = JOIN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
llthread_validate(_this);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLLThread::llthread_destroy(llthread_t *_this)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
/* thread not started */
|
||||||
|
if (!IS(_this, STARTED)) {
|
||||||
|
llthread_cleanup_child(_this);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DETACHED */
|
||||||
|
if (IS(_this, DETACHED)) {
|
||||||
|
if (IS(_this, JOINABLE)) {
|
||||||
|
llthread_detach(_this);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ATTACHED */
|
||||||
|
if (!IS(_this, JOINED)) {
|
||||||
|
llthread_join(_this, INFINITE_JOIN_TIMEOUT);
|
||||||
|
if (!IS(_this, JOINED)) {
|
||||||
|
/* @todo use current lua state to logging */
|
||||||
|
/*
|
||||||
|
* char buf[ERROR_LEN];
|
||||||
|
* strerror_r(errno, buf, ERROR_LEN);
|
||||||
|
* llthread_log(L, "Error can not join thread on gc: ", buf);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (IS(_this, JOINABLE)) {
|
||||||
|
llthread_cleanup_child(_this);
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
FREE_STRUCT(_this);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLLThread::llthread_alive(llthread_t *_this)
|
||||||
|
{
|
||||||
|
llthread_validate(_this);
|
||||||
|
|
||||||
|
if (IS(_this, JOINED)) {
|
||||||
|
return JOIN_OK;
|
||||||
|
} else {
|
||||||
|
int rc = pthread_kill(_this->thread, 0);
|
||||||
|
if (rc == 0) { /* still alive */
|
||||||
|
return JOIN_ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc != ESRCH) {
|
||||||
|
/*@fixme what else it can be ?*/
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
return JOIN_OK;
|
||||||
|
}
|
||||||
|
}
|
152
src/gui/lua/lua_threads.h
Normal file
152
src/gui/lua/lua_threads.h
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Copyright (c) 2011 by Robert G. Jakabosky <bobby@sharedrealm.com>
|
||||||
|
* Copyright (c) 2015 M. Liebmann (micha-bbg)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _LLTHREAD_H_
|
||||||
|
#define _LLTHREAD_H_
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include <lua.h>
|
||||||
|
#include <lauxlib.h>
|
||||||
|
#include <lualib.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wrap strerror_r(). */
|
||||||
|
#ifndef strerror_r
|
||||||
|
#define strerror_r __strerror_r
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define OS_THREAD_RETURN void *
|
||||||
|
#define INFINITE_JOIN_TIMEOUT -1
|
||||||
|
#define JOIN_OK 0
|
||||||
|
#define JOIN_ETIMEDOUT ETIMEDOUT
|
||||||
|
typedef int join_timeout_t;
|
||||||
|
typedef pthread_t os_thread_t;
|
||||||
|
|
||||||
|
#define ERROR_LEN 1024
|
||||||
|
|
||||||
|
#define flags_t unsigned char
|
||||||
|
|
||||||
|
#define FLAG_NONE (flags_t)0
|
||||||
|
#define FLAG_STARTED (flags_t)1<<0
|
||||||
|
#define FLAG_DETACHED (flags_t)1<<1
|
||||||
|
#define FLAG_JOINED (flags_t)1<<2
|
||||||
|
#define FLAG_JOINABLE (flags_t)1<<3
|
||||||
|
|
||||||
|
/*At least one flag*/
|
||||||
|
#define FLAG_IS_SET(O, F) (O->flags & (flags_t)(F))
|
||||||
|
#define FLAG_SET(O, F) O->flags |= (flags_t)(F)
|
||||||
|
#define FLAG_UNSET(O, F) O->flags &= ~((flags_t)(F))
|
||||||
|
#define IS(O, F) FLAG_IS_SET(O, FLAG_##F)
|
||||||
|
#define SET(O, F) FLAG_SET(O, FLAG_##F)
|
||||||
|
|
||||||
|
#define ALLOC_STRUCT(S) (S*)calloc(1, sizeof(S))
|
||||||
|
#define FREE_STRUCT(O) free(O)
|
||||||
|
|
||||||
|
#define LLTHREAD_NAME "threads"
|
||||||
|
#define LLTHREAD_TAG LLTHREAD_NAME
|
||||||
|
#define LLTHREAD_LOGGER_HOLDER LLTHREAD_NAME " logger holder"
|
||||||
|
|
||||||
|
typedef struct llthread_child_t {
|
||||||
|
lua_State* L;
|
||||||
|
int status;
|
||||||
|
flags_t flags;
|
||||||
|
} llthread_child_t;
|
||||||
|
|
||||||
|
typedef struct llthread_t {
|
||||||
|
llthread_child_t* child;
|
||||||
|
os_thread_t thread;
|
||||||
|
flags_t flags;
|
||||||
|
} llthread_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
lua_State* from_L;
|
||||||
|
lua_State* to_L;
|
||||||
|
int has_cache;
|
||||||
|
int cache_idx;
|
||||||
|
int is_arg;
|
||||||
|
} llthread_copy_state;
|
||||||
|
|
||||||
|
#if LUA_VERSION_NUM >= 503 /* Lua 5.3 */
|
||||||
|
|
||||||
|
#ifndef luaL_optint
|
||||||
|
# define luaL_optint luaL_optinteger
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef luaL_checkint
|
||||||
|
# define luaL_checkint luaL_checkinteger
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* Lua 5.3 */
|
||||||
|
|
||||||
|
int __strerror_r(int err, char* buf, size_t len);
|
||||||
|
|
||||||
|
class CLLThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CLLThread() {};
|
||||||
|
// ~CLLThread() {};
|
||||||
|
static CLLThread* getInstance();
|
||||||
|
static void LuaThreadsRegister(lua_State *L);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void llthread_log(lua_State *L, const char *hdr, const char *msg);
|
||||||
|
static int fail(lua_State *L, const char *msg);
|
||||||
|
static int traceback (lua_State *L);
|
||||||
|
static void open_thread_libs(lua_State *L);
|
||||||
|
static llthread_child_t *llthread_child_new();
|
||||||
|
static llthread_t *llthread_new();
|
||||||
|
static int llthread_push_args(lua_State *L, llthread_child_t *child, int idx, int top);
|
||||||
|
static int llthread_push_results(lua_State *L, llthread_child_t *child, int idx, int top);
|
||||||
|
static void llthread_validate(llthread_t *_this);
|
||||||
|
static llthread_t *llthread_create(lua_State *L, const char *code, size_t code_len);
|
||||||
|
static llthread_t *l_llthread_at (lua_State *L, int i);
|
||||||
|
static void llthread_child_destroy(llthread_child_t *_this);
|
||||||
|
static void llthread_cleanup_child(llthread_t *_this);
|
||||||
|
static int llthread_detach(llthread_t *_this);
|
||||||
|
static void* llthread_child_thread_run(void *arg);
|
||||||
|
static int llthread_start(llthread_t *_this, int start_detached, int joinable);
|
||||||
|
static int llthread_cancel(llthread_t *_this);
|
||||||
|
static int llthread_join(llthread_t *_this, join_timeout_t timeout);
|
||||||
|
static void llthread_destroy(llthread_t *_this);
|
||||||
|
static int llthread_alive(llthread_t *_this);
|
||||||
|
|
||||||
|
/* copy.cpp */
|
||||||
|
static int llthread_copy_table_from_cache(llthread_copy_state *state, int idx);
|
||||||
|
static int llthread_copy_value(llthread_copy_state *state, int depth, int idx);
|
||||||
|
static int llthread_copy_values(lua_State *from_L, lua_State *to_L, int idx, int top, int is_arg);
|
||||||
|
|
||||||
|
/* lua_functions.cpp */
|
||||||
|
static int l_llthread_new(lua_State *L);
|
||||||
|
static int l_llthread_start(lua_State *L);
|
||||||
|
static int l_llthread_cancel(lua_State *L);
|
||||||
|
static int l_llthread_join(lua_State *L);
|
||||||
|
static int l_llthread_alive(lua_State *L);
|
||||||
|
static int l_llthread_set_logger(lua_State *L);
|
||||||
|
static int l_llthread_started(lua_State *L);
|
||||||
|
static int l_llthread_detached(lua_State *L);
|
||||||
|
static int l_llthread_joinable(lua_State *L);
|
||||||
|
static int l_llthread_delete(lua_State *L);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _LLTHREAD_H_
|
167
src/gui/lua/lua_threads_copy.cpp
Normal file
167
src/gui/lua/lua_threads_copy.cpp
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Copyright (c) 2011 by Robert G. Jakabosky <bobby@sharedrealm.com>
|
||||||
|
* Copyright (c) 2015 M. Liebmann (micha-bbg)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "lua_threads.h"
|
||||||
|
|
||||||
|
/* maximum recursive depth of table copies. */
|
||||||
|
#define MAX_COPY_DEPTH 30
|
||||||
|
|
||||||
|
int CLLThread::llthread_copy_table_from_cache(llthread_copy_state *state, int idx)
|
||||||
|
{
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
/* convert table to pointer for lookup in cache. */
|
||||||
|
ptr = (void *)lua_topointer(state->from_L, idx);
|
||||||
|
if (ptr == NULL) return 0; /* can't convert to pointer. */
|
||||||
|
|
||||||
|
/* check if we need to create the cache. */
|
||||||
|
if (!state->has_cache) {
|
||||||
|
lua_newtable(state->to_L);
|
||||||
|
lua_replace(state->to_L, state->cache_idx);
|
||||||
|
state->has_cache = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pushlightuserdata(state->to_L, ptr);
|
||||||
|
lua_rawget(state->to_L, state->cache_idx);
|
||||||
|
if (lua_isnil(state->to_L, -1)) {
|
||||||
|
/* not in cache. */
|
||||||
|
lua_pop(state->to_L, 1);
|
||||||
|
/* create new table and add to cache. */
|
||||||
|
lua_newtable(state->to_L);
|
||||||
|
lua_pushlightuserdata(state->to_L, ptr);
|
||||||
|
lua_pushvalue(state->to_L, -2);
|
||||||
|
lua_rawset(state->to_L, state->cache_idx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* found table in cache. */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLLThread::llthread_copy_value(llthread_copy_state *state, int depth, int idx)
|
||||||
|
{
|
||||||
|
const char *str;
|
||||||
|
size_t str_len;
|
||||||
|
|
||||||
|
/* Maximum recursive depth */
|
||||||
|
if (++depth > MAX_COPY_DEPTH) {
|
||||||
|
return luaL_error(state->from_L, "Hit maximum copy depth (%d > %d).", depth, MAX_COPY_DEPTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only support string/number/boolean/nil/table/lightuserdata. */
|
||||||
|
switch (lua_type(state->from_L, idx)) {
|
||||||
|
case LUA_TNIL:
|
||||||
|
lua_pushnil(state->to_L);
|
||||||
|
break;
|
||||||
|
case LUA_TNUMBER:
|
||||||
|
lua_pushnumber(state->to_L, lua_tonumber(state->from_L, idx));
|
||||||
|
break;
|
||||||
|
case LUA_TBOOLEAN:
|
||||||
|
lua_pushboolean(state->to_L, lua_toboolean(state->from_L, idx));
|
||||||
|
break;
|
||||||
|
case LUA_TSTRING:
|
||||||
|
str = lua_tolstring(state->from_L, idx, &(str_len));
|
||||||
|
lua_pushlstring(state->to_L, str, str_len);
|
||||||
|
break;
|
||||||
|
case LUA_TLIGHTUSERDATA:
|
||||||
|
lua_pushlightuserdata(state->to_L, lua_touserdata(state->from_L, idx));
|
||||||
|
break;
|
||||||
|
case LUA_TTABLE:
|
||||||
|
/* make sure there is room on the new state for 3 values (table,key,value) */
|
||||||
|
if (!lua_checkstack(state->to_L, 3)) {
|
||||||
|
return luaL_error(state->from_L, "To stack overflow!");
|
||||||
|
}
|
||||||
|
/* make room on from stack for key/value pairs. */
|
||||||
|
luaL_checkstack(state->from_L, 2, "From stack overflow!");
|
||||||
|
|
||||||
|
/* check cache for table. */
|
||||||
|
if (llthread_copy_table_from_cache(state, idx)) {
|
||||||
|
/* found in cache don't need to copy table. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lua_pushnil(state->from_L);
|
||||||
|
while (lua_next(state->from_L, idx) != 0) {
|
||||||
|
/* key is at (top - 1), value at (top), but we need to normalize these
|
||||||
|
* to positive indices */
|
||||||
|
int kv_pos = lua_gettop(state->from_L);
|
||||||
|
/* copy key */
|
||||||
|
llthread_copy_value(state, depth, kv_pos - 1);
|
||||||
|
/* copy value */
|
||||||
|
llthread_copy_value(state, depth, kv_pos);
|
||||||
|
/* Copied key and value are now at -2 and -1 in state->to_L. */
|
||||||
|
lua_settable(state->to_L, -3);
|
||||||
|
/* Pop value for next iteration */
|
||||||
|
lua_pop(state->from_L, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LUA_TFUNCTION:
|
||||||
|
if (lua_iscfunction(state->from_L, idx)) {
|
||||||
|
lua_CFunction fn = lua_tocfunction(state->from_L, idx);
|
||||||
|
lua_pushcfunction(state->to_L, fn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LUA_TUSERDATA:
|
||||||
|
case LUA_TTHREAD:
|
||||||
|
default:
|
||||||
|
if (state->is_arg) {
|
||||||
|
return luaL_argerror(state->from_L, idx, "function/userdata/thread types un-supported.");
|
||||||
|
} else {
|
||||||
|
/* convert un-supported types to an error string. */
|
||||||
|
lua_pushfstring(state->to_L, "Un-supported value: %s: %p",
|
||||||
|
lua_typename(state->from_L, lua_type(state->from_L, idx)), lua_topointer(state->from_L, idx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLLThread::llthread_copy_values(lua_State *from_L, lua_State *to_L, int idx, int top, int is_arg)
|
||||||
|
{
|
||||||
|
llthread_copy_state state;
|
||||||
|
int nvalues = 0;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
nvalues = (top - idx) + 1;
|
||||||
|
/* make sure there is room on the new state for the values. */
|
||||||
|
if (!lua_checkstack(to_L, nvalues + 1)) {
|
||||||
|
return luaL_error(from_L, "To stack overflow!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setup copy state. */
|
||||||
|
state.from_L = from_L;
|
||||||
|
state.to_L = to_L;
|
||||||
|
state.is_arg = is_arg;
|
||||||
|
state.has_cache = 0; /* don't create cache table unless it is needed. */
|
||||||
|
lua_pushnil(to_L);
|
||||||
|
state.cache_idx = lua_gettop(to_L);
|
||||||
|
|
||||||
|
nvalues = 0;
|
||||||
|
for (n = idx; n <= top; n++) {
|
||||||
|
llthread_copy_value(&state, 0, n);
|
||||||
|
++nvalues;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove cache table. */
|
||||||
|
lua_remove(to_L, state.cache_idx);
|
||||||
|
|
||||||
|
return nvalues;
|
||||||
|
}
|
264
src/gui/lua/lua_threads_functions.cpp
Normal file
264
src/gui/lua/lua_threads_functions.cpp
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Copyright (c) 2011 by Robert G. Jakabosky <bobby@sharedrealm.com>
|
||||||
|
* Copyright (c) 2015 M. Liebmann (micha-bbg)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <memory.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include "lua_threads.h"
|
||||||
|
|
||||||
|
void CLLThread::LuaThreadsRegister(lua_State *L)
|
||||||
|
{
|
||||||
|
luaL_Reg meth[] = {
|
||||||
|
{ "new", CLLThread::l_llthread_new },
|
||||||
|
{ "start", CLLThread::l_llthread_start },
|
||||||
|
{ "cancel", CLLThread::l_llthread_cancel },
|
||||||
|
{ "join", CLLThread::l_llthread_join },
|
||||||
|
#if 0
|
||||||
|
/* Fix me */
|
||||||
|
{ "set_logger", CLLThread::l_llthread_set_logger },
|
||||||
|
#endif
|
||||||
|
{ "started", CLLThread::l_llthread_started },
|
||||||
|
{ "detached", CLLThread::l_llthread_detached },
|
||||||
|
{ "joinable", CLLThread::l_llthread_joinable },
|
||||||
|
{ "__gc", CLLThread::l_llthread_delete },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
luaL_newmetatable(L, LLTHREAD_TAG);
|
||||||
|
luaL_setfuncs(L, meth, 0);
|
||||||
|
lua_pushvalue(L, -1);
|
||||||
|
lua_setfield(L, -1, "__index");
|
||||||
|
lua_setglobal(L, LLTHREAD_TAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLLThread::l_llthread_new(lua_State *L)
|
||||||
|
{
|
||||||
|
size_t lua_code_len; const char *lua_code = luaL_checklstring(L, 1, &lua_code_len);
|
||||||
|
|
||||||
|
llthread_t **_this = (llthread_t **) lua_newuserdata(L, sizeof(llthread_t *));
|
||||||
|
luaL_getmetatable(L, LLTHREAD_TAG);
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
lua_insert(L, 2); /*move self prior args*/
|
||||||
|
*_this = llthread_create(L, lua_code, lua_code_len);
|
||||||
|
|
||||||
|
lua_settop(L, 2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLLThread::l_llthread_start(lua_State *L)
|
||||||
|
{
|
||||||
|
llthread_t *_this = l_llthread_at(L, 1);
|
||||||
|
int start_detached = lua_toboolean(L, 2);
|
||||||
|
int joinable, rc;
|
||||||
|
|
||||||
|
if (!lua_isnone(L, 3))
|
||||||
|
joinable = lua_toboolean(L, 3);
|
||||||
|
else
|
||||||
|
joinable = start_detached ? 0 : 1;
|
||||||
|
|
||||||
|
if (IS(_this, STARTED)) {
|
||||||
|
return fail(L, "Thread already started.");
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = llthread_start(_this, start_detached, joinable);
|
||||||
|
if (rc != 0) {
|
||||||
|
char buf[ERROR_LEN];
|
||||||
|
strerror_r(errno, buf, ERROR_LEN);
|
||||||
|
return fail(L, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_settop(L, 1); // return _this
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLLThread::l_llthread_cancel(lua_State *L)
|
||||||
|
{
|
||||||
|
llthread_t *_this = l_llthread_at(L, 1);
|
||||||
|
/* llthread_child_t *child = _this->child; */
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (!IS(_this, STARTED )) {
|
||||||
|
return fail(L, "Can't cancel a thread that hasn't be started.");
|
||||||
|
}
|
||||||
|
if ( IS(_this, DETACHED)) {
|
||||||
|
return fail(L, "Can't cancel a thread that has been detached.");
|
||||||
|
}
|
||||||
|
if ( IS(_this, JOINED )) {
|
||||||
|
return fail(L, "Can't cancel a thread that has already been joined.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cancel the thread. */
|
||||||
|
rc = llthread_cancel(_this);
|
||||||
|
|
||||||
|
if ( rc == JOIN_ETIMEDOUT ) {
|
||||||
|
lua_pushboolean(L, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == JOIN_OK) {
|
||||||
|
lua_pushboolean(L, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[ERROR_LEN];
|
||||||
|
strerror_r(errno, buf, ERROR_LEN);
|
||||||
|
/* llthread_cleanup_child(_this); */
|
||||||
|
return fail(L, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLLThread::l_llthread_join(lua_State *L)
|
||||||
|
{
|
||||||
|
llthread_t *_this = l_llthread_at(L, 1);
|
||||||
|
llthread_child_t *child = _this->child;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (!IS(_this, STARTED )) {
|
||||||
|
return fail(L, "Can't join a thread that hasn't be started.");
|
||||||
|
}
|
||||||
|
if ( IS(_this, DETACHED) && !IS(_this, JOINABLE)) {
|
||||||
|
return fail(L, "Can't join a thread that has been detached.");
|
||||||
|
}
|
||||||
|
if ( IS(_this, JOINED )) {
|
||||||
|
return fail(L, "Can't join a thread that has already been joined.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* join the thread. */
|
||||||
|
rc = llthread_join(_this, luaL_optint(L, 2, INFINITE_JOIN_TIMEOUT));
|
||||||
|
|
||||||
|
if (child && IS(_this, JOINED)) {
|
||||||
|
int top;
|
||||||
|
|
||||||
|
if (IS(_this, DETACHED) || !IS(_this, JOINABLE)) {
|
||||||
|
/*child lua state has been destroyed by child thread*/
|
||||||
|
/*@todo return thread exit code*/
|
||||||
|
lua_pushboolean(L, 1);
|
||||||
|
lua_pushnumber(L, 0);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy values from child lua state */
|
||||||
|
if (child->status != 0) {
|
||||||
|
const char *err_msg = lua_tostring(child->L, -1);
|
||||||
|
lua_pushboolean(L, 0);
|
||||||
|
lua_pushfstring(L, "Error from child thread: %s", err_msg);
|
||||||
|
top = 2;
|
||||||
|
} else {
|
||||||
|
lua_pushboolean(L, 1);
|
||||||
|
top = lua_gettop(child->L);
|
||||||
|
/* return results to parent thread. */
|
||||||
|
llthread_push_results(L, child, 2, top);
|
||||||
|
}
|
||||||
|
|
||||||
|
// llthread_cleanup_child(_this);
|
||||||
|
return top;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( rc == JOIN_ETIMEDOUT ) {
|
||||||
|
return fail(L, "timeout");
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[ERROR_LEN];
|
||||||
|
strerror_r(errno, buf, ERROR_LEN);
|
||||||
|
/* llthread_cleanup_child(_this); */
|
||||||
|
return fail(L, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLLThread::l_llthread_alive(lua_State *L)
|
||||||
|
{
|
||||||
|
llthread_t *_this = l_llthread_at(L, 1);
|
||||||
|
/* llthread_child_t *child = _this->child; */
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (!IS(_this, STARTED )) {
|
||||||
|
return fail(L, "Can't join a thread that hasn't be started.");
|
||||||
|
}
|
||||||
|
if ( IS(_this, DETACHED) && !IS(_this, JOINABLE)) {
|
||||||
|
return fail(L, "Can't join a thread that has been detached.");
|
||||||
|
}
|
||||||
|
if ( IS(_this, JOINED )) {
|
||||||
|
return fail(L, "Can't join a thread that has already been joined.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* join the thread. */
|
||||||
|
rc = llthread_alive(_this);
|
||||||
|
|
||||||
|
if ( rc == JOIN_ETIMEDOUT ) {
|
||||||
|
lua_pushboolean(L, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == JOIN_OK) {
|
||||||
|
lua_pushboolean(L, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[ERROR_LEN];
|
||||||
|
strerror_r(errno, buf, ERROR_LEN);
|
||||||
|
/* llthread_cleanup_child(_this); */
|
||||||
|
return fail(L, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLLThread::l_llthread_set_logger(lua_State *L)
|
||||||
|
{
|
||||||
|
lua_settop(L, 1);
|
||||||
|
luaL_argcheck(L, lua_isfunction(L, 1), 1, "function expected");
|
||||||
|
lua_rawsetp(L, LUA_REGISTRYINDEX, LLTHREAD_LOGGER_HOLDER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLLThread::l_llthread_started(lua_State *L)
|
||||||
|
{
|
||||||
|
llthread_t *_this = l_llthread_at(L, 1);
|
||||||
|
lua_pushboolean(L, IS(_this, STARTED)?1:0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLLThread::l_llthread_detached(lua_State *L)
|
||||||
|
{
|
||||||
|
llthread_t *_this = l_llthread_at(L, 1);
|
||||||
|
lua_pushboolean(L, IS(_this, DETACHED)?1:0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLLThread::l_llthread_joinable(lua_State *L)
|
||||||
|
{
|
||||||
|
llthread_t *_this = l_llthread_at(L, 1);
|
||||||
|
lua_pushboolean(L, IS(_this, JOINABLE)?1:0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CLLThread::l_llthread_delete(lua_State *L)
|
||||||
|
{
|
||||||
|
llthread_t **pthis = (llthread_t **)luaL_checkudata(L, 1, LLTHREAD_TAG);
|
||||||
|
luaL_argcheck (L, pthis != NULL, 1, "thread expected");
|
||||||
|
if (*pthis == NULL) return 0;
|
||||||
|
llthread_destroy(*pthis);
|
||||||
|
*pthis = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@@ -46,6 +46,7 @@
|
|||||||
#include "lua_menue.h"
|
#include "lua_menue.h"
|
||||||
#include "lua_messagebox.h"
|
#include "lua_messagebox.h"
|
||||||
#include "lua_misc.h"
|
#include "lua_misc.h"
|
||||||
|
#include "lua_threads.h"
|
||||||
#include "lua_video.h"
|
#include "lua_video.h"
|
||||||
|
|
||||||
extern CPictureViewer * g_PicViewer;
|
extern CPictureViewer * g_PicViewer;
|
||||||
@@ -402,7 +403,7 @@ CLuaInstance::CLuaInstance()
|
|||||||
lua = luaL_newstate();
|
lua = luaL_newstate();
|
||||||
|
|
||||||
/* register standard + custom functions. */
|
/* register standard + custom functions. */
|
||||||
registerFunctions();
|
LuaInstRegisterFunctions(lua);
|
||||||
}
|
}
|
||||||
|
|
||||||
CLuaInstance::~CLuaInstance()
|
CLuaInstance::~CLuaInstance()
|
||||||
@@ -508,7 +509,17 @@ void CLuaInstance::abortScript()
|
|||||||
lua_sethook(lua, &abortHook, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
|
lua_sethook(lua, &abortHook, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const luaL_Reg CLuaInstance::methods[] =
|
#ifdef STATIC_LUAPOSIX
|
||||||
|
/* hack: we link against luaposix, which is included in our
|
||||||
|
* custom built lualib */
|
||||||
|
extern "C" { LUAMOD_API int (luaopen_posix_c) (lua_State *L); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* load basic functions and register our own C callbacks */
|
||||||
|
void LuaInstRegisterFunctions(lua_State *L, bool fromThreads/*=false*/)
|
||||||
|
{
|
||||||
|
// ------------------------------------------
|
||||||
|
const luaL_Reg methods[] =
|
||||||
{
|
{
|
||||||
{ "GetInput", CLuaInstance::GetInput },
|
{ "GetInput", CLuaInstance::GetInput },
|
||||||
{ "Blit", CLuaInstance::Blit },
|
{ "Blit", CLuaInstance::Blit },
|
||||||
@@ -529,7 +540,7 @@ const luaL_Reg CLuaInstance::methods[] =
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
lua_misc.cpp
|
lua_misc.cpp
|
||||||
Deprecated, for the future separate class for misc functions
|
Deprecated, for the future using separate class for misc functions
|
||||||
*/
|
*/
|
||||||
{ "strFind", CLuaInstMisc::getInstance()->strFind_old },
|
{ "strFind", CLuaInstMisc::getInstance()->strFind_old },
|
||||||
{ "strSub", CLuaInstMisc::getInstance()->strSub_old },
|
{ "strSub", CLuaInstMisc::getInstance()->strSub_old },
|
||||||
@@ -540,7 +551,7 @@ const luaL_Reg CLuaInstance::methods[] =
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
lua_video.cpp
|
lua_video.cpp
|
||||||
Deprecated, for the future separate class for video
|
Deprecated, for the future using separate class for video
|
||||||
*/
|
*/
|
||||||
{ "setBlank", CLuaInstVideo::getInstance()->setBlank_old },
|
{ "setBlank", CLuaInstVideo::getInstance()->setBlank_old },
|
||||||
{ "ShowPicture", CLuaInstVideo::getInstance()->ShowPicture_old },
|
{ "ShowPicture", CLuaInstVideo::getInstance()->ShowPicture_old },
|
||||||
@@ -551,55 +562,55 @@ const luaL_Reg CLuaInstance::methods[] =
|
|||||||
{ "createChannelIDfromUrl", CLuaInstVideo::getInstance()->createChannelIDfromUrl_old },
|
{ "createChannelIDfromUrl", CLuaInstVideo::getInstance()->createChannelIDfromUrl_old },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
// ------------------------------------------
|
||||||
|
int top;
|
||||||
|
if (fromThreads)
|
||||||
|
top = lua_gettop(L);
|
||||||
|
|
||||||
#ifdef STATIC_LUAPOSIX
|
luaL_openlibs(L);
|
||||||
/* hack: we link against luaposix, which is included in our
|
luaopen_table(L);
|
||||||
* custom built lualib */
|
luaopen_io(L);
|
||||||
extern "C" { LUAMOD_API int (luaopen_posix_c) (lua_State *L); }
|
luaopen_string(L);
|
||||||
#endif
|
luaopen_math(L);
|
||||||
|
lua_newtable(L);
|
||||||
|
int methodtable = lua_gettop(L);
|
||||||
|
luaL_newmetatable(L, LUA_CLASSNAME);
|
||||||
|
int metatable = lua_gettop(L);
|
||||||
|
lua_pushliteral(L, "__metatable");
|
||||||
|
lua_pushvalue(L, methodtable);
|
||||||
|
lua_settable(L, metatable);
|
||||||
|
|
||||||
/* load basic functions and register our own C callbacks */
|
lua_pushliteral(L, "__index");
|
||||||
void CLuaInstance::registerFunctions()
|
lua_pushvalue(L, methodtable);
|
||||||
{
|
lua_settable(L, metatable);
|
||||||
luaL_openlibs(lua);
|
|
||||||
luaopen_table(lua);
|
|
||||||
luaopen_io(lua);
|
|
||||||
luaopen_string(lua);
|
|
||||||
luaopen_math(lua);
|
|
||||||
lua_newtable(lua);
|
|
||||||
int methodtable = lua_gettop(lua);
|
|
||||||
luaL_newmetatable(lua, className);
|
|
||||||
int metatable = lua_gettop(lua);
|
|
||||||
lua_pushliteral(lua, "__metatable");
|
|
||||||
lua_pushvalue(lua, methodtable);
|
|
||||||
lua_settable(lua, metatable);
|
|
||||||
|
|
||||||
lua_pushliteral(lua, "__index");
|
lua_pushliteral(L, "__gc");
|
||||||
lua_pushvalue(lua, methodtable);
|
lua_pushcfunction(L, CLuaInstance::GCWindow);
|
||||||
lua_settable(lua, metatable);
|
lua_settable(L, metatable);
|
||||||
|
|
||||||
lua_pushliteral(lua, "__gc");
|
lua_pop(L, 1);
|
||||||
lua_pushcfunction(lua, GCWindow);
|
|
||||||
lua_settable(lua, metatable);
|
|
||||||
|
|
||||||
lua_pop(lua, 1);
|
luaL_setfuncs(L, methods, 0);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
luaL_setfuncs(lua, methods, 0);
|
lua_register(L, LUA_CLASSNAME, CLuaInstance::NewWindow);
|
||||||
lua_pop(lua, 1);
|
|
||||||
|
|
||||||
lua_register(lua, className, NewWindow);
|
if (fromThreads)
|
||||||
|
lua_settop(L, top);
|
||||||
CLuaInstCCPicture::getInstance()->CCPictureRegister(lua);
|
// ------------------------------------------
|
||||||
CLuaInstCCSignalbox::getInstance()->CCSignalBoxRegister(lua);
|
CLuaInstCCPicture::getInstance()->CCPictureRegister(L);
|
||||||
CLuaInstCCText::getInstance()->CCTextRegister(lua);
|
CLuaInstCCSignalbox::getInstance()->CCSignalBoxRegister(L);
|
||||||
CLuaInstCCWindow::getInstance()->CCWindowRegister(lua);
|
CLuaInstCCText::getInstance()->CCTextRegister(L);
|
||||||
CLuaInstConfigFile::getInstance()->LuaConfigFileRegister(lua);
|
CLuaInstCCWindow::getInstance()->CCWindowRegister(L);
|
||||||
CLuaInstCurl::getInstance()->LuaCurlRegister(lua);
|
CLuaInstConfigFile::getInstance()->LuaConfigFileRegister(L);
|
||||||
CLuaInstHintbox::getInstance()->HintboxRegister(lua);
|
CLuaInstCurl::getInstance()->LuaCurlRegister(L);
|
||||||
CLuaInstMenu::getInstance()->MenuRegister(lua);
|
CLuaInstHintbox::getInstance()->HintboxRegister(L);
|
||||||
CLuaInstMessagebox::getInstance()->MessageboxRegister(lua);
|
CLuaInstMenu::getInstance()->MenuRegister(L);
|
||||||
CLuaInstMisc::getInstance()->LuaMiscRegister(lua);
|
CLuaInstMessagebox::getInstance()->MessageboxRegister(L);
|
||||||
CLuaInstVideo::getInstance()->LuaVideoRegister(lua);
|
CLuaInstMisc::getInstance()->LuaMiscRegister(L);
|
||||||
|
CLuaInstVideo::getInstance()->LuaVideoRegister(L);
|
||||||
|
if (!fromThreads)
|
||||||
|
CLLThread::getInstance()->LuaThreadsRegister(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
CLuaData *CLuaInstance::CheckData(lua_State *L, int narg)
|
CLuaData *CLuaInstance::CheckData(lua_State *L, int narg)
|
||||||
@@ -653,10 +664,10 @@ int CLuaInstance::GCWindow(lua_State *L)
|
|||||||
CNeutrinoFonts::getInstance()->deleteDynFontExtAll();
|
CNeutrinoFonts::getInstance()->deleteDynFontExtAll();
|
||||||
|
|
||||||
/* restoreNeutrino at plugin closing, when blocked from plugin */
|
/* restoreNeutrino at plugin closing, when blocked from plugin */
|
||||||
LUA_DEBUG(">>>>[%s:%d] (restoreNeutrino()) BlockedFromPlugin: %d, Playing: %d\n", __func__, __LINE__,
|
bool block = CMoviePlayerGui::getInstance().getBlockedFromPlugin();
|
||||||
CMoviePlayerGui::getInstance().getBlockedFromPlugin, CMoviePlayerGui::getInstance().Playing());
|
bool play = CMoviePlayerGui::getInstance().Playing();
|
||||||
if (CMoviePlayerGui::getInstance().getBlockedFromPlugin() &&
|
LUA_DEBUG(">>>>[%s:%d] (restoreNeutrino()) BlockedFromPlugin: %d, Playing: %d\n", __func__, __LINE__, block, play);
|
||||||
CMoviePlayerGui::getInstance().Playing()) {
|
if (block && play) {
|
||||||
CMoviePlayerGui::getInstance().setBlockedFromPlugin(false);
|
CMoviePlayerGui::getInstance().setBlockedFromPlugin(false);
|
||||||
CMoviePlayerGui::getInstance().restoreNeutrino();
|
CMoviePlayerGui::getInstance().restoreNeutrino();
|
||||||
}
|
}
|
||||||
|
@@ -31,14 +31,14 @@ extern "C" {
|
|||||||
#include "luainstance_helpers.h"
|
#include "luainstance_helpers.h"
|
||||||
|
|
||||||
#define LUA_API_VERSION_MAJOR 1
|
#define LUA_API_VERSION_MAJOR 1
|
||||||
#define LUA_API_VERSION_MINOR 33
|
#define LUA_API_VERSION_MINOR 34
|
||||||
|
|
||||||
|
void LuaInstRegisterFunctions(lua_State *L, bool fromThreads=false);
|
||||||
|
|
||||||
/* inspired by Steve Kemp http://www.steve.org.uk/ */
|
/* inspired by Steve Kemp http://www.steve.org.uk/ */
|
||||||
class CLuaInstance
|
class CLuaInstance
|
||||||
{
|
{
|
||||||
static const char className[];
|
static const char className[];
|
||||||
static const luaL_Reg methods[];
|
|
||||||
static const luaL_Reg menu_methods[];
|
|
||||||
static CLuaData *CheckData(lua_State *L, int narg);
|
static CLuaData *CheckData(lua_State *L, int narg);
|
||||||
public:
|
public:
|
||||||
CLuaInstance();
|
CLuaInstance();
|
||||||
@@ -58,10 +58,6 @@ public:
|
|||||||
// The last parameter to NULL is imperative.
|
// The last parameter to NULL is imperative.
|
||||||
void runScript(const char *fileName, const char *arg0, ...);
|
void runScript(const char *fileName, const char *arg0, ...);
|
||||||
|
|
||||||
private:
|
|
||||||
lua_State* lua;
|
|
||||||
void registerFunctions();
|
|
||||||
|
|
||||||
static int NewWindow(lua_State *L);
|
static int NewWindow(lua_State *L);
|
||||||
static int GCWindow(lua_State *L);
|
static int GCWindow(lua_State *L);
|
||||||
static int GetInput(lua_State *L);
|
static int GetInput(lua_State *L);
|
||||||
@@ -80,6 +76,10 @@ private:
|
|||||||
static int saveScreen(lua_State *L);
|
static int saveScreen(lua_State *L);
|
||||||
static int restoreScreen(lua_State *L);
|
static int restoreScreen(lua_State *L);
|
||||||
static int deleteSavedScreen(lua_State *L);
|
static int deleteSavedScreen(lua_State *L);
|
||||||
|
|
||||||
|
private:
|
||||||
|
lua_State* lua;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _LUAINSTANCE_H */
|
#endif /* _LUAINSTANCE_H */
|
||||||
|
Reference in New Issue
Block a user