Browse Source

Lua data exchange between different Lua states

bel2125 7 years ago
parent
commit
8dcad3dff1
4 changed files with 205 additions and 14 deletions
  1. 2 1
      Qt/CivetWeb.pro
  2. 1 0
      format.bat
  3. 27 13
      src/mod_lua.inl
  4. 175 0
      src/mod_lua_shared.inl

+ 2 - 1
Qt/CivetWeb.pro

@@ -14,7 +14,8 @@ SOURCES += \
     ../src/timer.inl \
     ../src/civetweb.c \
     ../src/main.c \
-    ../src/mod_zlib.inl
+    ../src/mod_zlib.inl \
+    ../src/mod_lua_shared.inl
 
 #include(deployment.pri)
 #qtcAddDeployment()

+ 1 - 0
format.bat

@@ -6,6 +6,7 @@ clang-format -i src/civetweb_private_lua.h
 clang-format -i src/md5.inl
 clang-format -i src/sha1.inl
 clang-format -i src/mod_lua.inl
+clang-format -i src/mod_lua_shared.inl
 clang-format -i src/mod_duktape.inl
 clang-format -i src/mod_zlib.inl
 clang-format -i src/timer.inl

+ 27 - 13
src/mod_lua.inl

@@ -2014,6 +2014,21 @@ prepare_lua_request_info(struct mg_connection *conn, lua_State *L)
 }
 
 
+static void *
+lua_allocator(void *ud, void *ptr, size_t osize, size_t nsize)
+{
+	(void)osize; /* not used */
+
+	if (nsize == 0) {
+		mg_free(ptr);
+		return NULL;
+	}
+	return mg_realloc_ctx(ptr, nsize, (struct mg_context *)ud);
+}
+
+#include "mod_lua_shared.inl"
+
+
 static void
 civetweb_open_lua_libs(lua_State *L)
 {
@@ -2187,8 +2202,12 @@ prepare_lua_environment(struct mg_context *ctx,
 		prepare_lua_request_info(conn, L);
 	}
 
+	/* Store as global table "mg" */
 	lua_setglobal(L, "mg");
 
+	/* Register "shared" table */
+	lua_shared_register(L);
+
 	/* Register default mg.onerror function */
 	IGNORE_UNUSED_RESULT(
 	    luaL_dostring(L,
@@ -2253,19 +2272,6 @@ lua_error_handler(lua_State *L)
 }
 
 
-static void *
-lua_allocator(void *ud, void *ptr, size_t osize, size_t nsize)
-{
-	(void)osize; /* not used */
-
-	if (nsize == 0) {
-		mg_free(ptr);
-		return NULL;
-	}
-	return mg_realloc_ctx(ptr, nsize, (struct mg_context *)ud);
-}
-
-
 static void
 mg_exec_lua_script(struct mg_connection *conn,
                    const char *path,
@@ -2804,6 +2810,10 @@ static void *lib_handle_uuid = NULL;
 static void
 lua_init_optional_libraries(void)
 {
+	/* shared Lua state */
+	lua_shared_init();
+
+/* UUID library */
 #if !defined(_WIN32)
 	lib_handle_uuid = dlopen("libuuid.so", RTLD_LAZY);
 	pf_uuid_generate.p =
@@ -2817,6 +2827,7 @@ lua_init_optional_libraries(void)
 static void
 lua_exit_optional_libraries(void)
 {
+/* UUID library */
 #if !defined(_WIN32)
 	if (lib_handle_uuid) {
 		dlclose(lib_handle_uuid);
@@ -2824,6 +2835,9 @@ lua_exit_optional_libraries(void)
 #endif
 	pf_uuid_generate.p = 0;
 	lib_handle_uuid = NULL;
+
+	/* shared Lua state */
+	lua_shared_exit();
 }
 
 

+ 175 - 0
src/mod_lua_shared.inl

@@ -0,0 +1,175 @@
+/* Copyright (c) 2018 CivetWeb developers
+ *
+ * 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.
+ */
+
+
+/* Shared data for all Lua states */
+static lua_State *L_shared;
+static pthread_mutex_t lua_shared_lock;
+
+void
+lua_shared_init(void)
+{
+	L_shared = lua_newstate(lua_allocator, NULL);
+	printf("Lsh: %p\n", L_shared);
+
+	lua_newtable(L_shared);
+	lua_setglobal(L_shared, "shared");
+
+	pthread_mutex_init(&lua_shared_lock, &pthread_mutex_attr);
+}
+
+
+void
+lua_shared_exit(void)
+{
+	printf("Lsh: %p\n", L_shared);
+
+	lua_close(L_shared);
+	L_shared = 0;
+
+	pthread_mutex_destroy(&lua_shared_lock);
+}
+
+
+static int
+lua_shared_index(struct lua_State *L)
+{
+	void *ud = lua_touserdata(L, 1);
+	int key_type = lua_type(L, 2);
+
+	printf("lua_shared_index call (%p)\n", ud);
+
+	if ((key_type != LUA_TNUMBER) && (key_type != LUA_TSTRING)
+	    && (key_type != LUA_TBOOLEAN)) {
+		return luaL_error(L, "shared index must be string, number or boolean");
+	}
+
+	pthread_mutex_lock(&lua_shared_lock);
+
+	lua_getglobal(L_shared, "shared");
+
+	if (key_type == LUA_TNUMBER) {
+		double num = lua_tonumber(L, 2);
+		printf("index: %G\n", num);
+		lua_pushnumber(L_shared, num);
+	} else if (key_type == LUA_TBOOLEAN) {
+		int i = lua_toboolean(L, 2);
+		printf("index: %s\n", i ? "true" : "false");
+		lua_pushboolean(L_shared, i);
+	} else {
+		size_t len = 0;
+		const char *str = lua_tolstring(L, 2, &len);
+		printf("index: %s\n", str);
+		lua_pushlstring(L_shared, str, len);
+	}
+
+	lua_rawget(L_shared, -2);
+
+	size_t len;
+	const char *s = lua_tolstring(L_shared, -1, &len);
+	printf("<%s>\n", s);
+
+	lua_pushlstring(L, s, len);
+
+	lua_pop(L_shared, 2);
+
+	pthread_mutex_unlock(&lua_shared_lock);
+
+	return 1;
+}
+
+
+static int
+lua_shared_newindex(struct lua_State *L)
+{
+	void *ud = lua_touserdata(L, 1);
+	int key_type = lua_type(L, 2);
+	int val_type = lua_type(L, 3);
+
+	printf("lua_shared_newindex call (%p)\n", ud);
+
+	if ((key_type != LUA_TNUMBER) && (key_type != LUA_TSTRING)
+	    && (key_type != LUA_TBOOLEAN)) {
+		return luaL_error(L, "shared index must be string, number or boolean");
+	}
+	if ((val_type != LUA_TNUMBER) && (val_type != LUA_TSTRING)
+	    && (val_type != LUA_TBOOLEAN)) {
+		return luaL_error(L, "shared value must be string, number or boolean");
+	}
+
+	pthread_mutex_lock(&lua_shared_lock);
+
+	lua_getglobal(L_shared, "shared");
+
+	if (key_type == LUA_TNUMBER) {
+		double num = lua_tonumber(L, 2);
+		printf("index: %G\n", num);
+		lua_pushnumber(L_shared, num);
+	} else if (key_type == LUA_TBOOLEAN) {
+		int i = lua_toboolean(L, 2);
+		printf("index: %s\n", i ? "true" : "false");
+		lua_pushboolean(L_shared, i);
+	} else {
+		size_t len = 0;
+		const char *str = lua_tolstring(L, 2, &len);
+		printf("index: %s\n", str);
+		lua_pushlstring(L_shared, str, len);
+	}
+
+	if (val_type == LUA_TNUMBER) {
+		double num = lua_tonumber(L, 3);
+		printf("index: %G\n", num);
+		lua_pushnumber(L_shared, num);
+	} else if (val_type == LUA_TBOOLEAN) {
+		int i = lua_toboolean(L, 3);
+		printf("index: %s\n", i ? "true" : "false");
+		lua_pushboolean(L_shared, i);
+	} else {
+		size_t len = 0;
+		const char *str = lua_tolstring(L, 3, &len);
+		printf("index: %s\n", str);
+		lua_pushlstring(L_shared, str, len);
+	}
+
+	lua_rawset(L_shared, -3);
+	lua_pop(L_shared, 1);
+
+	pthread_mutex_unlock(&lua_shared_lock);
+
+	return 0;
+}
+
+
+void
+lua_shared_register(struct lua_State *L)
+{
+	lua_newuserdata(L, 0);
+	lua_newtable(L);
+	lua_pushliteral(L, "__index");
+	lua_pushcclosure(L, lua_shared_index, 0);
+	lua_rawset(L, -3);
+	lua_pushliteral(L, "__newindex");
+	lua_pushcclosure(L, lua_shared_newindex, 0);
+	lua_rawset(L, -3);
+	lua_setmetatable(L, -2);
+
+	lua_setglobal(L, "shared");
+}