diff options
author | Natanael Copa <ncopa@alpinelinux.org> | 2013-08-30 13:55:38 +0000 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2013-08-30 13:55:38 +0000 |
commit | 7bb75c03f72a307c1cff91d4c89fdbb34a4d9455 (patch) | |
tree | 13c686280d8ed043c2df1dd49b2515ecd920f907 /testing | |
parent | c35aa3d58d6c8b907da81441140b22b8dc8514a6 (diff) | |
download | aports-7bb75c03f72a307c1cff91d4c89fdbb34a4d9455.tar.bz2 aports-7bb75c03f72a307c1cff91d4c89fdbb34a4d9455.tar.xz |
testing/lua5.2-llthreads: new aport
Low-Level native threads module for Lua
https://github.com/Neopallium/lua-llthreads
Diffstat (limited to 'testing')
-rw-r--r-- | testing/lua5.2-llthreads/APKBUILD | 57 | ||||
-rw-r--r-- | testing/lua5.2-llthreads/bindings-1.patch | 650 | ||||
-rw-r--r-- | testing/lua5.2-llthreads/bindings-2.patch | 109 | ||||
-rw-r--r-- | testing/lua5.2-llthreads/lua-5.2.patch | 336 |
4 files changed, 1152 insertions, 0 deletions
diff --git a/testing/lua5.2-llthreads/APKBUILD b/testing/lua5.2-llthreads/APKBUILD new file mode 100644 index 000000000..b201e35ed --- /dev/null +++ b/testing/lua5.2-llthreads/APKBUILD @@ -0,0 +1,57 @@ +# Contributor: Natanael Copa <ncopa@alpinelinux.org> +# Maintainer: Natanael Copa <ncopa@alpinelinux.org> +pkgname=lua5.2-llthreads +pkgver=1.2 +pkgrel=0 +pkgdesc="Low-Level native threads module for Lua" +url="https://github.com/Neopallium/lua-llthreads" +arch="all" +license="MIT" +depends="" +makedepends="cmake lua5.2-dev" +install="" +subpackages= +source="lua-llthreads-$pkgver.tar.gz::https://github.com/Neopallium/lua-llthreads/archive/v$pkgver.tar.gz + bindings-1.patch + bindings-2.patch + lua-5.2.patch" + +_builddir="$srcdir"/lua-llthreads-$pkgver + +prepare() { + local i + cd "$_builddir" + for i in $source; do + case $i in + *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;; + esac + done +} + +build() { + cd "$_builddir" + _luaver=$(lua -e 'print((_VERSION:match("^Lua (%d+%.%d+)")))') + cmake \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DINSTALL_CMOD=/usr/lib/lua/$_luaver \ + . || return 1 + make || return 1 +} + +package() { + cd "$_builddir" + make install DESTDIR="$pkgdir" || return 1 +} + +md5sums="d4adb2e6d4859bf33ebdb3bd6b6c6bb5 lua-llthreads-1.2.tar.gz +399fa42d7dfa7ec2335bd7111b17935e bindings-1.patch +f892e9cb699eef2d5df406063a26d044 bindings-2.patch +5f4a0b8c23968a521072c96c42435475 lua-5.2.patch" +sha256sums="32df7dc903760825536def63fba834466c42e6bd17022d430893c9a6ca3ba8f2 lua-llthreads-1.2.tar.gz +20c2cc64f09dd601fb85d867e7e57b8849a66d9b1992c647282a84af92127902 bindings-1.patch +3bb62563bdd5e4b5261612b5d0498bed4b327f02c7b5ff4a85329b9bc7867b3c bindings-2.patch +5c7f28e7a3ef4e8d1ac6f0ef5cf5680ba58d0aa76e77260d6fe1c4ed74c4b586 lua-5.2.patch" +sha512sums="d8b006e7f135e9c45d88c93d6acf30d41024bee66bd0747ba8112e28c2fe03fbd8f869d6235261108f3df30a08f3a812595a763c82a57674b5ec54a8ca915fa7 lua-llthreads-1.2.tar.gz +eace4eb6226527697aa82b5e455b7ece3d651966f3525471f07476d84714550bb4f75447be34569d57f2ed52bbfd708458305b527621179cfa2f843ae684d931 bindings-1.patch +fd5be1ec7293c0e279877ee139de53c1772c28957c30e276f5fe8e05314c31e81ae6ea18553fe67d912b3f9902b48cd88b962480f5855037783477bbb633e019 bindings-2.patch +234e0afe81bbd2a40689a858febec8778962273553da6d7b876871bd996ed0ad28ca33a15b7e155c313b63f10b0f8bab3ee0a83c0cd14d3378884d0031df720d lua-5.2.patch" diff --git a/testing/lua5.2-llthreads/bindings-1.patch b/testing/lua5.2-llthreads/bindings-1.patch new file mode 100644 index 000000000..72c116f4f --- /dev/null +++ b/testing/lua5.2-llthreads/bindings-1.patch @@ -0,0 +1,650 @@ +From dee5a6fabc51c22607fefb5f7a9dd8fe32d098aa Mon Sep 17 00:00:00 2001 +From: "Robert G. Jakabosky" <bobby@sharedrealm.com> +Date: Mon, 13 Feb 2012 01:47:15 -0800 +Subject: [PATCH] Update pre-generated bindings. + +--- + src/pre_generated-llthreads.nobj.c | 378 +++++++++++++++++++++++++++++-------- + 1 file changed, 302 insertions(+), 76 deletions(-) + +diff --git a/src/pre_generated-llthreads.nobj.c b/src/pre_generated-llthreads.nobj.c +index 6f53fe5..a7ce73a 100644 +--- a/src/pre_generated-llthreads.nobj.c ++++ b/src/pre_generated-llthreads.nobj.c +@@ -10,13 +10,14 @@ + #include "lauxlib.h" + #include "lualib.h" + +- +- + #define REG_PACKAGE_IS_CONSTRUCTOR 0 ++#define REG_MODULES_AS_GLOBALS 0 + #define REG_OBJECTS_AS_GLOBALS 0 + #define OBJ_DATA_HIDDEN_METATABLE 1 +-#define LUAJIT_FFI 0 + #define USE_FIELD_GET_SET_METHODS 0 ++#define LUAJIT_FFI 0 ++ ++ + + + +@@ -95,19 +96,26 @@ + #define assert_obj_type(type, obj) + #endif + +-#ifndef obj_type_free ++void *nobj_realloc(void *ptr, size_t osize, size_t nsize); ++ ++void *nobj_realloc(void *ptr, size_t osize, size_t nsize) { ++ (void)osize; ++ if(0 == nsize) { ++ free(ptr); ++ return NULL; ++ } ++ return realloc(ptr, nsize); ++} ++ + #define obj_type_free(type, obj) do { \ + assert_obj_type(type, obj); \ +- free((obj)); \ ++ nobj_realloc((obj), sizeof(type), 0); \ + } while(0) +-#endif + +-#ifndef obj_type_new + #define obj_type_new(type, obj) do { \ + assert_obj_type(type, obj); \ +- (obj) = malloc(sizeof(type)); \ ++ (obj) = nobj_realloc(NULL, 0, sizeof(type)); \ + } while(0) +-#endif + + typedef struct obj_type obj_type; + +@@ -165,15 +173,22 @@ struct obj_type { + uint32_t flags; /**< is_writable:1bit */ + } obj_field; + ++typedef enum { ++ REG_OBJECT, ++ REG_PACKAGE, ++ REG_META, ++} module_reg_type; ++ + typedef struct reg_sub_module { + obj_type *type; +- int is_package; ++ module_reg_type req_type; + const luaL_reg *pub_funcs; + const luaL_reg *methods; + const luaL_reg *metas; + const obj_base *bases; + const obj_field *fields; + const obj_const *constants; ++ int bidirectional_consts; + } reg_sub_module; + + #define OBJ_UDATA_FLAG_OWN (1<<0) +@@ -185,18 +200,26 @@ struct obj_type { + } obj_udata; + + /* use static pointer as key to weak userdata table. */ +-static char *obj_udata_weak_ref_key = "obj_udata_weak_ref_key"; ++static char obj_udata_weak_ref_key[] = "obj_udata_weak_ref_key"; ++ ++/* use static pointer as key to module's private table. */ ++static char obj_udata_private_key[] = "obj_udata_private_key"; + + #if LUAJIT_FFI ++typedef int (*ffi_export_func_t)(void); + typedef struct ffi_export_symbol { + const char *name; +- void *sym; ++ union { ++ void *data; ++ ffi_export_func_t func; ++ } sym; + } ffi_export_symbol; + #endif + + + + ++ + static obj_type obj_types[] = { + #define obj_type_id_Lua_LLThread 0 + #define obj_type_Lua_LLThread (obj_types[obj_type_id_Lua_LLThread]) +@@ -205,10 +228,101 @@ struct obj_type { + }; + + ++#if LUAJIT_FFI ++ ++/* nobj_ffi_support_enabled_hint should be set to 1 when FFI support is enabled in at-least one ++ * instance of a LuaJIT state. It should never be set back to 0. */ ++static int nobj_ffi_support_enabled_hint = 0; ++static const char nobj_ffi_support_key[] = "LuaNativeObject_FFI_SUPPORT"; ++static const char nobj_check_ffi_support_code[] = ++"local stat, ffi=pcall(require,\"ffi\")\n" /* try loading LuaJIT`s FFI module. */ ++"if not stat then return false end\n" ++"return true\n"; ++ ++static int nobj_check_ffi_support(lua_State *L) { ++ int rc; ++ int err; ++ ++ /* check if ffi test has already been done. */ ++ lua_pushstring(L, nobj_ffi_support_key); ++ lua_rawget(L, LUA_REGISTRYINDEX); ++ if(!lua_isnil(L, -1)) { ++ rc = lua_toboolean(L, -1); ++ lua_pop(L, 1); ++ return rc; /* return results of previous check. */ ++ } ++ lua_pop(L, 1); /* pop nil. */ ++ ++ err = luaL_loadbuffer(L, nobj_check_ffi_support_code, ++ sizeof(nobj_check_ffi_support_code) - 1, nobj_ffi_support_key); ++ if(0 == err) { ++ err = lua_pcall(L, 0, 1, 0); ++ } ++ if(err) { ++ const char *msg = "<err not a string>"; ++ if(lua_isstring(L, -1)) { ++ msg = lua_tostring(L, -1); ++ } ++ printf("Error when checking for FFI-support: %s\n", msg); ++ lua_pop(L, 1); /* pop error message. */ ++ return 0; ++ } ++ /* check results of test. */ ++ rc = lua_toboolean(L, -1); ++ lua_pop(L, 1); /* pop results. */ ++ /* cache results. */ ++ lua_pushstring(L, nobj_ffi_support_key); ++ lua_pushboolean(L, rc); ++ lua_rawset(L, LUA_REGISTRYINDEX); ++ ++ /* turn-on hint that there is FFI code enabled. */ ++ if(rc) { ++ nobj_ffi_support_enabled_hint = 1; ++ } ++ ++ return rc; ++} ++ ++static int nobj_try_loading_ffi(lua_State *L, const char *ffi_mod_name, ++ const char *ffi_init_code, const ffi_export_symbol *ffi_exports, int priv_table) ++{ ++ int err; ++ ++ /* export symbols to priv_table. */ ++ while(ffi_exports->name != NULL) { ++ lua_pushstring(L, ffi_exports->name); ++ lua_pushlightuserdata(L, ffi_exports->sym.data); ++ lua_settable(L, priv_table); ++ ffi_exports++; ++ } ++ err = luaL_loadbuffer(L, ffi_init_code, strlen(ffi_init_code), ffi_mod_name); ++ if(0 == err) { ++ lua_pushvalue(L, -2); /* dup C module's table. */ ++ lua_pushvalue(L, priv_table); /* move priv_table to top of stack. */ ++ lua_remove(L, priv_table); ++ lua_pushvalue(L, LUA_REGISTRYINDEX); ++ err = lua_pcall(L, 3, 0, 0); ++ } ++ if(err) { ++ const char *msg = "<err not a string>"; ++ if(lua_isstring(L, -1)) { ++ msg = lua_tostring(L, -1); ++ } ++ printf("Failed to install FFI-based bindings: %s\n", msg); ++ lua_pop(L, 1); /* pop error message. */ ++ } ++ return err; ++} ++#endif ++ + #ifndef REG_PACKAGE_IS_CONSTRUCTOR + #define REG_PACKAGE_IS_CONSTRUCTOR 1 + #endif + ++#ifndef REG_MODULES_AS_GLOBALS ++#define REG_MODULES_AS_GLOBALS 0 ++#endif ++ + #ifndef REG_OBJECTS_AS_GLOBALS + #define REG_OBJECTS_AS_GLOBALS 0 + #endif +@@ -296,6 +410,25 @@ static FUNC_UNUSED obj_udata *obj_udata_luacheck_internal(lua_State *L, int _ind + return ud; + } + } ++ } else { ++ /* handle cdata. */ ++ /* get private table. */ ++ lua_pushlightuserdata(L, obj_udata_private_key); ++ lua_rawget(L, LUA_REGISTRYINDEX); /* private table. */ ++ /* get cdata type check function from private table. */ ++ lua_pushlightuserdata(L, type); ++ lua_rawget(L, -2); ++ ++ /* pass cdata value to type checking function. */ ++ lua_pushvalue(L, _index); ++ lua_call(L, 1, 1); ++ if(!lua_isnil(L, -1)) { ++ /* valid type get pointer from cdata. */ ++ lua_pop(L, 2); ++ *obj = *(void **)lua_topointer(L, _index); ++ return ud; ++ } ++ lua_pop(L, 2); + } + if(not_delete) { + luaL_typerror(L, _index, type->name); /* is not a userdata value. */ +@@ -309,6 +442,15 @@ static FUNC_UNUSED void *obj_udata_luacheck(lua_State *L, int _index, obj_type * + return obj; + } + ++static FUNC_UNUSED void *obj_udata_luaoptional(lua_State *L, int _index, obj_type *type) { ++ void *obj = NULL; ++ if(lua_isnil(L, _index)) { ++ return obj; ++ } ++ obj_udata_luacheck_internal(L, _index, &(obj), type, 1); ++ return obj; ++} ++ + static FUNC_UNUSED void *obj_udata_luadelete(lua_State *L, int _index, obj_type *type, int *flags) { + void *obj; + obj_udata *ud = obj_udata_luacheck_internal(L, _index, &(obj), type, 0); +@@ -327,6 +469,17 @@ static FUNC_UNUSED void obj_udata_luapush(lua_State *L, void *obj, obj_type *typ + lua_pushnil(L); + return; + } ++#if LUAJIT_FFI ++ lua_pushlightuserdata(L, type); ++ lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ ++ if(nobj_ffi_support_enabled_hint && lua_isfunction(L, -1)) { ++ /* call special FFI "void *" to FFI object convertion function. */ ++ lua_pushlightuserdata(L, obj); ++ lua_pushinteger(L, flags); ++ lua_call(L, 2, 1); ++ return; ++ } ++#endif + /* check for type caster. */ + if(type->dcaster) { + (type->dcaster)(&obj, &type); +@@ -336,8 +489,12 @@ static FUNC_UNUSED void obj_udata_luapush(lua_State *L, void *obj, obj_type *typ + ud->obj = obj; + ud->flags = flags; + /* get obj_type metatable. */ ++#if LUAJIT_FFI ++ lua_insert(L, -2); /* move userdata below metatable. */ ++#else + lua_pushlightuserdata(L, type); + lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ ++#endif + lua_setmetatable(L, -2); + } + +@@ -383,6 +540,18 @@ static FUNC_UNUSED void obj_udata_luapush_weak(lua_State *L, void *obj, obj_type + } + lua_pop(L, 1); /* pop nil. */ + ++#if LUAJIT_FFI ++ lua_pushlightuserdata(L, type); ++ lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ ++ if(nobj_ffi_support_enabled_hint && lua_isfunction(L, -1)) { ++ lua_remove(L, -2); ++ /* call special FFI "void *" to FFI object convertion function. */ ++ lua_pushlightuserdata(L, obj); ++ lua_pushinteger(L, flags); ++ lua_call(L, 2, 1); ++ return; ++ } ++#endif + /* create new userdata. */ + ud = (obj_udata *)lua_newuserdata(L, sizeof(obj_udata)); + +@@ -390,8 +559,12 @@ static FUNC_UNUSED void obj_udata_luapush_weak(lua_State *L, void *obj, obj_type + ud->obj = obj; + ud->flags = flags; + /* get obj_type metatable. */ ++#if LUAJIT_FFI ++ lua_insert(L, -2); /* move userdata below metatable. */ ++#else + lua_pushlightuserdata(L, type); + lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ ++#endif + lua_setmetatable(L, -2); + + /* add weak reference to object. */ +@@ -455,15 +628,39 @@ static FUNC_UNUSED void * obj_simple_udata_luacheck(lua_State *L, int _index, ob + return ud; + } + } ++ } else { ++ /* handle cdata. */ ++ /* get private table. */ ++ lua_pushlightuserdata(L, obj_udata_private_key); ++ lua_rawget(L, LUA_REGISTRYINDEX); /* private table. */ ++ /* get cdata type check function from private table. */ ++ lua_pushlightuserdata(L, type); ++ lua_rawget(L, -2); ++ ++ /* pass cdata value to type checking function. */ ++ lua_pushvalue(L, _index); ++ lua_call(L, 1, 1); ++ if(!lua_isnil(L, -1)) { ++ /* valid type get pointer from cdata. */ ++ lua_pop(L, 2); ++ return (void *)lua_topointer(L, _index); ++ } ++ lua_pop(L, 2); + } + luaL_typerror(L, _index, type->name); /* is not a userdata value. */ + return NULL; + } + +-static FUNC_UNUSED void * obj_simple_udata_luadelete(lua_State *L, int _index, obj_type *type, int *flags) { ++static FUNC_UNUSED void * obj_simple_udata_luaoptional(lua_State *L, int _index, obj_type *type) { ++ if(lua_isnil(L, _index)) { ++ return NULL; ++ } ++ return obj_simple_udata_luacheck(L, _index, type); ++} ++ ++static FUNC_UNUSED void * obj_simple_udata_luadelete(lua_State *L, int _index, obj_type *type) { + void *obj; + obj = obj_simple_udata_luacheck(L, _index, type); +- *flags = OBJ_UDATA_FLAG_OWN; + /* clear the metatable to invalidate userdata. */ + lua_pushnil(L); + lua_setmetatable(L, _index); +@@ -472,12 +669,26 @@ static FUNC_UNUSED void * obj_simple_udata_luadelete(lua_State *L, int _index, o + + static FUNC_UNUSED void *obj_simple_udata_luapush(lua_State *L, void *obj, int size, obj_type *type) + { ++#if LUAJIT_FFI ++ lua_pushlightuserdata(L, type); ++ lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ ++ if(nobj_ffi_support_enabled_hint && lua_isfunction(L, -1)) { ++ /* call special FFI "void *" to FFI object convertion function. */ ++ lua_pushlightuserdata(L, obj); ++ lua_call(L, 1, 1); ++ return obj; ++ } ++#endif + /* create new userdata. */ + void *ud = lua_newuserdata(L, size); + memcpy(ud, obj, size); + /* get obj_type metatable. */ ++#if LUAJIT_FFI ++ lua_insert(L, -2); /* move userdata below metatable. */ ++#else + lua_pushlightuserdata(L, type); + lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ ++#endif + lua_setmetatable(L, -2); + + return ud; +@@ -526,7 +737,8 @@ static int obj_constructor_call_wrapper(lua_State *L) { + return lua_gettop(L); + } + +-static void obj_type_register_constants(lua_State *L, const obj_const *constants, int tab_idx) { ++static void obj_type_register_constants(lua_State *L, const obj_const *constants, int tab_idx, ++ int bidirectional) { + /* register constants. */ + while(constants->name != NULL) { + lua_pushstring(L, constants->name); +@@ -544,6 +756,22 @@ static void obj_type_register_constants(lua_State *L, const obj_const *constants + lua_pushnil(L); + break; + } ++ /* map values back to keys. */ ++ if(bidirectional) { ++ /* check if value already exists. */ ++ lua_pushvalue(L, -1); ++ lua_rawget(L, tab_idx - 3); ++ if(lua_isnil(L, -1)) { ++ lua_pop(L, 1); ++ /* add value->key mapping. */ ++ lua_pushvalue(L, -1); ++ lua_pushvalue(L, -3); ++ lua_rawset(L, tab_idx - 4); ++ } else { ++ /* value already exists. */ ++ lua_pop(L, 1); ++ } ++ } + lua_rawset(L, tab_idx - 2); + constants++; + } +@@ -558,20 +786,48 @@ static void obj_type_register_package(lua_State *L, const reg_sub_module *type_r + luaL_register(L, NULL, reg_list); + } + +- obj_type_register_constants(L, type_reg->constants, -1); ++ obj_type_register_constants(L, type_reg->constants, -1, type_reg->bidirectional_consts); + + lua_pop(L, 1); /* drop package table */ + } + ++static void obj_type_register_meta(lua_State *L, const reg_sub_module *type_reg) { ++ const luaL_reg *reg_list; ++ ++ /* create public functions table. */ ++ reg_list = type_reg->pub_funcs; ++ if(reg_list != NULL && reg_list[0].name != NULL) { ++ /* register functions */ ++ luaL_register(L, NULL, reg_list); ++ } ++ ++ obj_type_register_constants(L, type_reg->constants, -1, type_reg->bidirectional_consts); ++ ++ /* register methods. */ ++ luaL_register(L, NULL, type_reg->methods); ++ ++ /* create metatable table. */ ++ lua_newtable(L); ++ luaL_register(L, NULL, type_reg->metas); /* fill metatable */ ++ /* setmetatable on meta-object. */ ++ lua_setmetatable(L, -2); ++ ++ lua_pop(L, 1); /* drop meta-object */ ++} ++ + static void obj_type_register(lua_State *L, const reg_sub_module *type_reg, int priv_table) { + const luaL_reg *reg_list; + obj_type *type = type_reg->type; + const obj_base *base = type_reg->bases; + +- if(type_reg->is_package == 1) { ++ if(type_reg->req_type == REG_PACKAGE) { + obj_type_register_package(L, type_reg); + return; + } ++ if(type_reg->req_type == REG_META) { ++ obj_type_register_meta(L, type_reg); ++ return; ++ } + + /* create public functions table. */ + reg_list = type_reg->pub_funcs; +@@ -620,14 +876,10 @@ static void obj_type_register(lua_State *L, const reg_sub_module *type_reg, int + lua_pushvalue(L, -2); /* dup metatable. */ + lua_rawset(L, LUA_REGISTRYINDEX); /* REGISTRY[type] = metatable */ + +-#if LUAJIT_FFI + /* add metatable to 'priv_table' */ + lua_pushstring(L, type->name); + lua_pushvalue(L, -2); /* dup metatable. */ + lua_rawset(L, priv_table); /* priv_table["<object_name>"] = metatable */ +-#else +- (void)priv_table; +-#endif + + luaL_register(L, NULL, type_reg->metas); /* fill metatable */ + +@@ -638,7 +890,7 @@ static void obj_type_register(lua_State *L, const reg_sub_module *type_reg, int + base++; + } + +- obj_type_register_constants(L, type_reg->constants, -2); ++ obj_type_register_constants(L, type_reg->constants, -2, type_reg->bidirectional_consts); + + lua_pushliteral(L, "__index"); + lua_pushvalue(L, -3); /* dup methods table */ +@@ -658,54 +910,12 @@ static FUNC_UNUSED int lua_checktype_ref(lua_State *L, int _index, int _type) { + return luaL_ref(L, LUA_REGISTRYINDEX); + } + +-#if LUAJIT_FFI +-static int nobj_udata_new_ffi(lua_State *L) { +- size_t size = luaL_checkinteger(L, 1); +- luaL_checktype(L, 2, LUA_TTABLE); +- lua_settop(L, 2); +- /* create userdata. */ +- lua_newuserdata(L, size); +- lua_replace(L, 1); +- /* set userdata's metatable. */ +- lua_setmetatable(L, 1); +- return 1; +-} +- +-static int nobj_try_loading_ffi(lua_State *L, const char *ffi_mod_name, +- const char *ffi_init_code, const ffi_export_symbol *ffi_exports, int priv_table) +-{ +- int err; +- +- /* export symbols to priv_table. */ +- while(ffi_exports->name != NULL) { +- lua_pushstring(L, ffi_exports->name); +- lua_pushlightuserdata(L, ffi_exports->sym); +- lua_settable(L, priv_table); +- ffi_exports++; +- } +- err = luaL_loadbuffer(L, ffi_init_code, strlen(ffi_init_code), ffi_mod_name); +- if(0 == err) { +- lua_pushvalue(L, -2); /* dup C module's table. */ +- lua_pushvalue(L, priv_table); /* move priv_table to top of stack. */ +- lua_remove(L, priv_table); +- lua_pushcfunction(L, nobj_udata_new_ffi); +- err = lua_pcall(L, 3, 0, 0); +- } +- if(err) { +- const char *msg = "<err not a string>"; +- if(lua_isstring(L, -1)) { +- msg = lua_tostring(L, -1); +- } +- printf("Failed to install FFI-based bindings: %s\n", msg); +- lua_pop(L, 1); /* pop error message. */ +- } +- return err; +-} +-#endif + + + #define obj_type_Lua_LLThread_check(L, _index) \ + obj_udata_luacheck(L, _index, &(obj_type_Lua_LLThread)) ++#define obj_type_Lua_LLThread_optional(L, _index) \ ++ obj_udata_luaoptional(L, _index, &(obj_type_Lua_LLThread)) + #define obj_type_Lua_LLThread_delete(L, _index, flags) \ + obj_udata_luadelete_weak(L, _index, &(obj_type_Lua_LLThread), flags) + #define obj_type_Lua_LLThread_push(L, obj, flags) \ +@@ -714,8 +924,6 @@ static int nobj_try_loading_ffi(lua_State *L, const char *ffi_mod_name, + + + +- +- + /* maximum recursive depth of table copies. */ + #define MAX_COPY_DEPTH 30 + +@@ -1106,7 +1314,7 @@ static Lua_LLThread *llthread_create(lua_State *L, const char *code, size_t code + + + +-/* method: delete */ ++/* method: _priv */ + static int Lua_LLThread__delete__meth(lua_State *L) { + int this_flags_idx1 = 0; + Lua_LLThread * this_idx1 = obj_type_Lua_LLThread_delete(L,1,&(this_flags_idx1)); +@@ -1264,14 +1472,21 @@ static int llthreads__new__func(lua_State *L) { + + + static const reg_sub_module reg_sub_modules[] = { +- { &(obj_type_Lua_LLThread), 0, obj_Lua_LLThread_pub_funcs, obj_Lua_LLThread_methods, obj_Lua_LLThread_metas, obj_Lua_LLThread_bases, obj_Lua_LLThread_fields, obj_Lua_LLThread_constants}, +- {NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL} ++ { &(obj_type_Lua_LLThread), REG_OBJECT, obj_Lua_LLThread_pub_funcs, obj_Lua_LLThread_methods, obj_Lua_LLThread_metas, obj_Lua_LLThread_bases, obj_Lua_LLThread_fields, obj_Lua_LLThread_constants, 0}, ++ {NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, 0} + }; + + + + + ++#if LUAJIT_FFI ++static const ffi_export_symbol llthreads_ffi_export[] = { ++ {NULL, { .data = NULL } } ++}; ++#endif ++ ++ + + + static const luaL_Reg submodule_libs[] = { +@@ -1304,20 +1519,26 @@ LUA_NOBJ_API int luaopen_llthreads(lua_State *L) { + const luaL_Reg *submodules = submodule_libs; + int priv_table = -1; + +-#if LUAJIT_FFI + /* private table to hold reference to object metatables. */ + lua_newtable(L); + priv_table = lua_gettop(L); +-#endif ++ lua_pushlightuserdata(L, obj_udata_private_key); ++ lua_pushvalue(L, priv_table); ++ lua_rawset(L, LUA_REGISTRYINDEX); /* store private table in registry. */ + + /* create object cache. */ + create_object_instance_cache(L); + + /* module table. */ ++#if REG_MODULES_AS_GLOBALS + luaL_register(L, "llthreads", llthreads_function); ++#else ++ lua_newtable(L); ++ luaL_register(L, NULL, llthreads_function); ++#endif + + /* register module constants. */ +- obj_type_register_constants(L, llthreads_constants, -1); ++ obj_type_register_constants(L, llthreads_constants, -1, 0); + + for(; submodules->func != NULL ; submodules++) { + lua_pushcfunction(L, submodules->func); +@@ -1338,9 +1559,14 @@ LUA_NOBJ_API int luaopen_llthreads(lua_State *L) { + } + + #if LUAJIT_FFI +- nobj_try_loading_ffi(L, "llthreads", llthreads_ffi_lua_code, +- llthreads_ffi_export, priv_table); ++ if(nobj_check_ffi_support(L)) { ++ nobj_try_loading_ffi(L, "llthreads", llthreads_ffi_lua_code, ++ llthreads_ffi_export, priv_table); ++ } + #endif ++ ++ ++ + return 1; + } + +-- +1.8.1.6 + diff --git a/testing/lua5.2-llthreads/bindings-2.patch b/testing/lua5.2-llthreads/bindings-2.patch new file mode 100644 index 000000000..226ba322c --- /dev/null +++ b/testing/lua5.2-llthreads/bindings-2.patch @@ -0,0 +1,109 @@ +From 25687f0babcc2b3cdc8b42c7ecf8a34f751062d6 Mon Sep 17 00:00:00 2001 +From: "Robert G. Jakabosky" <bobby@sharedrealm.com> +Date: Fri, 2 Mar 2012 17:34:04 -0800 +Subject: [PATCH] Re-generate bindings. + +--- + src/pre_generated-llthreads.nobj.c | 35 +++++++++++++++++++++++++++++------ + 1 file changed, 29 insertions(+), 6 deletions(-) + +diff --git a/src/pre_generated-llthreads.nobj.c b/src/pre_generated-llthreads.nobj.c +index b2d1185..d016651 100644 +--- a/src/pre_generated-llthreads.nobj.c ++++ b/src/pre_generated-llthreads.nobj.c +@@ -56,7 +56,7 @@ + #define true 1 + #endif + #ifndef false +-#define false 1 ++#define false 0 + #endif + + #endif +@@ -250,7 +250,8 @@ static int nobj_check_ffi_support(lua_State *L) { + if(!lua_isnil(L, -1)) { + rc = lua_toboolean(L, -1); + lua_pop(L, 1); +- return rc; /* return results of previous check. */ ++ /* use results of previous check. */ ++ goto finished; + } + lua_pop(L, 1); /* pop nil. */ + +@@ -276,6 +277,7 @@ static int nobj_check_ffi_support(lua_State *L) { + lua_pushboolean(L, rc); + lua_rawset(L, LUA_REGISTRYINDEX); + ++finished: + /* turn-on hint that there is FFI code enabled. */ + if(rc) { + nobj_ffi_support_enabled_hint = 1; +@@ -284,9 +286,29 @@ static int nobj_check_ffi_support(lua_State *L) { + return rc; + } + ++typedef struct { ++ const char **ffi_init_code; ++ int offset; ++} nobj_reader_state; ++ ++static const char *nobj_lua_Reader(lua_State *L, void *data, size_t *size) { ++ nobj_reader_state *state = (nobj_reader_state *)data; ++ const char *ptr; ++ ++ ptr = state->ffi_init_code[state->offset]; ++ if(ptr != NULL) { ++ *size = strlen(ptr); ++ state->offset++; ++ } else { ++ *size = 0; ++ } ++ return ptr; ++} ++ + static int nobj_try_loading_ffi(lua_State *L, const char *ffi_mod_name, +- const char *ffi_init_code, const ffi_export_symbol *ffi_exports, int priv_table) ++ const char *ffi_init_code[], const ffi_export_symbol *ffi_exports, int priv_table) + { ++ nobj_reader_state state = { ffi_init_code, 0 }; + int err; + + /* export symbols to priv_table. */ +@@ -296,7 +318,7 @@ static int nobj_try_loading_ffi(lua_State *L, const char *ffi_mod_name, + lua_settable(L, priv_table); + ffi_exports++; + } +- err = luaL_loadbuffer(L, ffi_init_code, strlen(ffi_init_code), ffi_mod_name); ++ err = lua_load(L, nobj_lua_Reader, &state, ffi_mod_name); + if(0 == err) { + lua_pushvalue(L, -2); /* dup C module's table. */ + lua_pushvalue(L, priv_table); /* move priv_table to top of stack. */ +@@ -670,6 +692,7 @@ static FUNC_UNUSED void * obj_simple_udata_luadelete(lua_State *L, int _index, o + + static FUNC_UNUSED void *obj_simple_udata_luapush(lua_State *L, void *obj, int size, obj_type *type) + { ++ void *ud; + #if LUAJIT_FFI + lua_pushlightuserdata(L, type); + lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ +@@ -681,7 +704,7 @@ static FUNC_UNUSED void *obj_simple_udata_luapush(lua_State *L, void *obj, int s + } + #endif + /* create new userdata. */ +- void *ud = lua_newuserdata(L, size); ++ ud = lua_newuserdata(L, size); + memcpy(ud, obj, size); + /* get obj_type metatable. */ + #if LUAJIT_FFI +@@ -1483,7 +1506,7 @@ static int llthreads__new__func(lua_State *L) { + + #if LUAJIT_FFI + static const ffi_export_symbol llthreads_ffi_export[] = { +- {NULL, { .data = NULL } } ++ {NULL, { NULL } } + }; + #endif + +-- +1.8.1.6 + diff --git a/testing/lua5.2-llthreads/lua-5.2.patch b/testing/lua5.2-llthreads/lua-5.2.patch new file mode 100644 index 000000000..354b4d42a --- /dev/null +++ b/testing/lua5.2-llthreads/lua-5.2.patch @@ -0,0 +1,336 @@ +From 58b5d127c94138e1c46fdbed993bea52c90585fd Mon Sep 17 00:00:00 2001 +From: "Robert G. Jakabosky" <bobby@sharedrealm.com> +Date: Tue, 16 Oct 2012 00:52:40 -0700 +Subject: [PATCH] Add support for Lua 5.2 + +--- + src/pre_generated-llthreads.nobj.c | 117 +++++++++++++++++++++++++++++-------- + src/thread.nobj.lua | 19 +++++- + 2 files changed, 110 insertions(+), 26 deletions(-) + +diff --git a/src/pre_generated-llthreads.nobj.c b/src/pre_generated-llthreads.nobj.c +index ed9c43b..ff70704 100644 +--- a/src/pre_generated-llthreads.nobj.c ++++ b/src/pre_generated-llthreads.nobj.c +@@ -10,6 +10,54 @@ + #include "lauxlib.h" + #include "lualib.h" + ++/* some Lua 5.0 compatibility support. */ ++#if !defined(lua_pushliteral) ++#define lua_pushliteral(L, s) lua_pushstring(L, "" s, (sizeof(s)/sizeof(char))-1) ++#endif ++ ++#if !defined(LUA_VERSION_NUM) ++#define lua_pushinteger(L, n) lua_pushnumber(L, (lua_Number)n) ++#define luaL_Reg luaL_reg ++#endif ++ ++/* some Lua 5.1 compatibility support. */ ++#if !defined(LUA_VERSION_NUM) || (LUA_VERSION_NUM == 501) ++/* ++** Adapted from Lua 5.2.0 ++*/ ++static void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { ++ luaL_checkstack(L, nup, "too many upvalues"); ++ for (; l->name != NULL; l++) { /* fill the table with given functions */ ++ int i; ++ for (i = 0; i < nup; i++) /* copy upvalues to the top */ ++ lua_pushvalue(L, -nup); ++ lua_pushstring(L, l->name); ++ lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ ++ lua_settable(L, -(nup + 3)); ++ } ++ lua_pop(L, nup); /* remove upvalues */ ++} ++ ++#define lua_load_no_mode(L, reader, data, source) \ ++ lua_load(L, reader, data, source) ++ ++#define lua_rawlen(L, idx) lua_objlen(L, idx) ++ ++#endif ++ ++#if LUA_VERSION_NUM == 502 ++ ++#define lua_load_no_mode(L, reader, data, source) \ ++ lua_load(L, reader, data, source, NULL) ++ ++static int luaL_typerror (lua_State *L, int narg, const char *tname) { ++ const char *msg = lua_pushfstring(L, "%s expected, got %s", ++ tname, luaL_typename(L, narg)); ++ return luaL_argerror(L, narg, msg); ++} ++ ++#endif ++ + #define REG_PACKAGE_IS_CONSTRUCTOR 0 + #define REG_MODULES_AS_GLOBALS 0 + #define REG_OBJECTS_AS_GLOBALS 0 +@@ -189,9 +237,9 @@ struct obj_type { + typedef struct reg_sub_module { + obj_type *type; + module_reg_type req_type; +- const luaL_reg *pub_funcs; +- const luaL_reg *methods; +- const luaL_reg *metas; ++ const luaL_Reg *pub_funcs; ++ const luaL_Reg *methods; ++ const luaL_Reg *metas; + const obj_base *bases; + const obj_field *fields; + const obj_const *constants; +@@ -326,7 +374,7 @@ static int nobj_try_loading_ffi(lua_State *L, const char *ffi_mod_name, + lua_settable(L, priv_table); + ffi_exports++; + } +- err = lua_load(L, nobj_lua_Reader, &state, ffi_mod_name); ++ err = lua_load_no_mode(L, nobj_lua_Reader, &state, ffi_mod_name); + if(0 == err) { + lua_pushvalue(L, -2); /* dup C module's table. */ + lua_pushvalue(L, priv_table); /* move priv_table to top of stack. */ +@@ -531,6 +579,12 @@ static void obj_type_register_implements(lua_State *L, const reg_impl *impls) { + #define REG_MODULES_AS_GLOBALS 0 + #endif + ++/* For Lua 5.2 don't register modules as globals. */ ++#if LUA_VERSION_NUM == 502 ++#undef REG_MODULES_AS_GLOBALS ++#define REG_MODULES_AS_GLOBALS 0 ++#endif ++ + #ifndef REG_OBJECTS_AS_GLOBALS + #define REG_OBJECTS_AS_GLOBALS 0 + #endif +@@ -591,7 +645,7 @@ static FUNC_UNUSED obj_udata *obj_udata_toobj(lua_State *L, int _index) { + luaL_typerror(L, _index, "userdata"); /* is not a userdata value. */ + } + /* verify userdata size. */ +- len = lua_objlen(L, _index); ++ len = lua_rawlen(L, _index); + if(len != sizeof(obj_udata)) { + /* This shouldn't be possible */ + luaL_error(L, "invalid userdata size: size=%d, expected=%d", len, sizeof(obj_udata)); +@@ -1007,9 +1061,9 @@ static FUNC_UNUSED void *obj_simple_udata_luapush(lua_State *L, void *obj, int s + /* default simple object equal method. */ + static FUNC_UNUSED int obj_simple_udata_default_equal(lua_State *L) { + void *ud1 = obj_simple_udata_toobj(L, 1); +- size_t len1 = lua_objlen(L, 1); ++ size_t len1 = lua_rawlen(L, 1); + void *ud2 = obj_simple_udata_toobj(L, 2); +- size_t len2 = lua_objlen(L, 2); ++ size_t len2 = lua_rawlen(L, 2); + + if(len1 == len2) { + lua_pushboolean(L, (memcmp(ud1, ud2, len1) == 0)); +@@ -1088,12 +1142,12 @@ static void obj_type_register_constants(lua_State *L, const obj_const *constants + } + + static void obj_type_register_package(lua_State *L, const reg_sub_module *type_reg) { +- const luaL_reg *reg_list = type_reg->pub_funcs; ++ const luaL_Reg *reg_list = type_reg->pub_funcs; + + /* create public functions table. */ + if(reg_list != NULL && reg_list[0].name != NULL) { + /* register functions */ +- luaL_register(L, NULL, reg_list); ++ luaL_setfuncs(L, reg_list, 0); + } + + obj_type_register_constants(L, type_reg->constants, -1, type_reg->bidirectional_consts); +@@ -1102,23 +1156,23 @@ static void obj_type_register_package(lua_State *L, const reg_sub_module *type_r + } + + static void obj_type_register_meta(lua_State *L, const reg_sub_module *type_reg) { +- const luaL_reg *reg_list; ++ const luaL_Reg *reg_list; + + /* create public functions table. */ + reg_list = type_reg->pub_funcs; + if(reg_list != NULL && reg_list[0].name != NULL) { + /* register functions */ +- luaL_register(L, NULL, reg_list); ++ luaL_setfuncs(L, reg_list, 0); + } + + obj_type_register_constants(L, type_reg->constants, -1, type_reg->bidirectional_consts); + + /* register methods. */ +- luaL_register(L, NULL, type_reg->methods); ++ luaL_setfuncs(L, type_reg->methods, 0); + + /* create metatable table. */ + lua_newtable(L); +- luaL_register(L, NULL, type_reg->metas); /* fill metatable */ ++ luaL_setfuncs(L, type_reg->metas, 0); /* fill metatable */ + /* setmetatable on meta-object. */ + lua_setmetatable(L, -2); + +@@ -1126,7 +1180,7 @@ static void obj_type_register_meta(lua_State *L, const reg_sub_module *type_reg) + } + + static void obj_type_register(lua_State *L, const reg_sub_module *type_reg, int priv_table) { +- const luaL_reg *reg_list; ++ const luaL_Reg *reg_list; + obj_type *type = type_reg->type; + const obj_base *base = type_reg->bases; + +@@ -1143,7 +1197,7 @@ static void obj_type_register(lua_State *L, const reg_sub_module *type_reg, int + reg_list = type_reg->pub_funcs; + if(reg_list != NULL && reg_list[0].name != NULL) { + /* register "constructors" as to object's public API */ +- luaL_register(L, NULL, reg_list); /* fill public API table. */ ++ luaL_setfuncs(L, reg_list, 0); /* fill public API table. */ + + /* make public API table callable as the default constructor. */ + lua_newtable(L); /* create metatable */ +@@ -1173,7 +1227,7 @@ static void obj_type_register(lua_State *L, const reg_sub_module *type_reg, int + #endif + } + +- luaL_register(L, NULL, type_reg->methods); /* fill methods table. */ ++ luaL_setfuncs(L, type_reg->methods, 0); /* fill methods table. */ + + luaL_newmetatable(L, type->name); /* create metatable */ + lua_pushliteral(L, ".name"); +@@ -1191,7 +1245,7 @@ static void obj_type_register(lua_State *L, const reg_sub_module *type_reg, int + lua_pushvalue(L, -2); /* dup metatable. */ + lua_rawset(L, priv_table); /* priv_table["<object_name>"] = metatable */ + +- luaL_register(L, NULL, type_reg->metas); /* fill metatable */ ++ luaL_setfuncs(L, type_reg->metas, 0); /* fill metatable */ + + /* add obj_bases to metatable. */ + while(base->id >= 0) { +@@ -1348,7 +1402,7 @@ static FUNC_UNUSED void *nobj_delete_callback_state(lua_State *L, int owner_idx) + #define ERROR_LEN 1024 + + /****************************************************************************** +-* traceback() function from Lua 5.1.x source. ++* traceback() function from Lua 5.1/5.2 source. + * Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining +@@ -1370,10 +1424,12 @@ static FUNC_UNUSED void *nobj_delete_callback_state(lua_State *L, int owner_idx) + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ******************************************************************************/ ++#if !defined(LUA_VERSION_NUM) || (LUA_VERSION_NUM == 501) ++/* from Lua 5.1 */ + static int traceback (lua_State *L) { + if (!lua_isstring(L, 1)) /* 'message' not a string? */ + return 1; /* keep it intact */ +- lua_getfield(L, LUA_GLOBALSINDEX, "debug"); ++ lua_getglobal(L, "debug"); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + return 1; +@@ -1388,6 +1444,19 @@ static int traceback (lua_State *L) { + lua_call(L, 2, 1); /* call debug.traceback */ + return 1; + } ++#else ++/* from Lua 5.2 */ ++static int 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; ++} ++#endif + + static Lua_LLThread_child *llthread_child_new() { + Lua_LLThread_child *this; +@@ -1831,17 +1900,17 @@ static int llthreads__new__func(lua_State *L) { + + + +-static const luaL_reg obj_Lua_LLThread_pub_funcs[] = { ++static const luaL_Reg obj_Lua_LLThread_pub_funcs[] = { + {NULL, NULL} + }; + +-static const luaL_reg obj_Lua_LLThread_methods[] = { ++static const luaL_Reg obj_Lua_LLThread_methods[] = { + {"start", Lua_LLThread__start__meth}, + {"join", Lua_LLThread__join__meth}, + {NULL, NULL} + }; + +-static const luaL_reg obj_Lua_LLThread_metas[] = { ++static const luaL_Reg obj_Lua_LLThread_metas[] = { + {"__gc", Lua_LLThread__delete__meth}, + {"__tostring", obj_udata_default_tostring}, + {"__eq", obj_udata_default_equal}, +@@ -1864,7 +1933,7 @@ static int llthreads__new__func(lua_State *L) { + {NULL, NULL} + }; + +-static const luaL_reg llthreads_function[] = { ++static const luaL_Reg llthreads_function[] = { + {"new", llthreads__new__func}, + {NULL, NULL} + }; +@@ -1941,7 +2010,7 @@ LUA_NOBJ_API int luaopen_llthreads(lua_State *L) { + luaL_register(L, "llthreads", llthreads_function); + #else + lua_newtable(L); +- luaL_register(L, NULL, llthreads_function); ++ luaL_setfuncs(L, llthreads_function, 0); + #endif + + /* register module constants. */ +diff --git a/src/thread.nobj.lua b/src/thread.nobj.lua +index 8d4ef54..626022f 100644 +--- a/src/thread.nobj.lua ++++ b/src/thread.nobj.lua +@@ -59,7 +59,7 @@ typedef struct Lua_LLThread { + #define ERROR_LEN 1024 + + /****************************************************************************** +-* traceback() function from Lua 5.1.x source. ++* traceback() function from Lua 5.1/5.2 source. + * Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining +@@ -81,10 +81,12 @@ typedef struct Lua_LLThread { + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ******************************************************************************/ ++#if !defined(LUA_VERSION_NUM) || (LUA_VERSION_NUM == 501) ++/* from Lua 5.1 */ + static int traceback (lua_State *L) { + if (!lua_isstring(L, 1)) /* 'message' not a string? */ + return 1; /* keep it intact */ +- lua_getfield(L, LUA_GLOBALSINDEX, "debug"); ++ lua_getglobal(L, "debug"); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + return 1; +@@ -99,6 +101,19 @@ static int traceback (lua_State *L) { + lua_call(L, 2, 1); /* call debug.traceback */ + return 1; + } ++#else ++/* from Lua 5.2 */ ++static int 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; ++} ++#endif + + static Lua_LLThread_child *llthread_child_new() { + Lua_LLThread_child *this; +-- +1.8.1.6 + |