|  | @@ -24,31 +24,39 @@
 | 
	
		
			
				|  |  |  static lua_State *L_shared;
 | 
	
		
			
				|  |  |  static pthread_mutex_t lua_shared_lock;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/* Library init.
 | 
	
		
			
				|  |  | + * This function must be called before all other functions. Not thread-safe. */
 | 
	
		
			
				|  |  |  void
 | 
	
		
			
				|  |  |  lua_shared_init(void)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | +	/* Create a new Lua state to store all shared data.
 | 
	
		
			
				|  |  | +	 * In fact, this is used as a hashmap. */
 | 
	
		
			
				|  |  |  	L_shared = lua_newstate(lua_allocator, NULL);
 | 
	
		
			
				|  |  | -	printf("Lsh: %p\n", L_shared);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	lua_newtable(L_shared);
 | 
	
		
			
				|  |  |  	lua_setglobal(L_shared, "shared");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	/* Mutex for locking access to the shared state from different threads. */
 | 
	
		
			
				|  |  |  	pthread_mutex_init(&lua_shared_lock, &pthread_mutex_attr);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +/* Library exit.
 | 
	
		
			
				|  |  | + * This function should be called for cleanup. Not thread-safe. */
 | 
	
		
			
				|  |  |  void
 | 
	
		
			
				|  |  |  lua_shared_exit(void)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -	printf("Lsh: %p\n", L_shared);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +	/* Destroy Lua state */
 | 
	
		
			
				|  |  |  	lua_close(L_shared);
 | 
	
		
			
				|  |  |  	L_shared = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	/* Destroy mutex. */
 | 
	
		
			
				|  |  |  	pthread_mutex_destroy(&lua_shared_lock);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +/* Read access to shared element (x = shared.element) */
 | 
	
		
			
				|  |  |  static int
 | 
	
		
			
				|  |  |  lua_shared_index(struct lua_State *L)
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -56,29 +64,39 @@ lua_shared_index(struct lua_State *L)
 | 
	
		
			
				|  |  |  	int key_type = lua_type(L, 2);
 | 
	
		
			
				|  |  |  	int val_type;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	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);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		pthread_mutex_lock(&lua_shared_lock);
 | 
	
		
			
				|  |  | +		lua_getglobal(L_shared, "shared");
 | 
	
		
			
				|  |  |  		lua_pushnumber(L_shared, num);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	} else if (key_type == LUA_TBOOLEAN) {
 | 
	
		
			
				|  |  |  		int i = lua_toboolean(L, 2);
 | 
	
		
			
				|  |  | -		printf("index: %s\n", i ? "true" : "false");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		pthread_mutex_lock(&lua_shared_lock);
 | 
	
		
			
				|  |  | +		lua_getglobal(L_shared, "shared");
 | 
	
		
			
				|  |  |  		lua_pushboolean(L_shared, i);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	} else {
 | 
	
		
			
				|  |  |  		size_t len = 0;
 | 
	
		
			
				|  |  |  		const char *str = lua_tolstring(L, 2, &len);
 | 
	
		
			
				|  |  | -		printf("index: %s\n", str);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		if ((len > 1) && (0 == memcmp(str, "__", 2))) {
 | 
	
		
			
				|  |  | +			/* Todo: return functions */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			/* Unknown reserved index */
 | 
	
		
			
				|  |  | +			lua_pushnil(L);
 | 
	
		
			
				|  |  | +			return 1;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		pthread_mutex_lock(&lua_shared_lock);
 | 
	
		
			
				|  |  | +		lua_getglobal(L_shared, "shared");
 | 
	
		
			
				|  |  |  		lua_pushlstring(L_shared, str, len);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -88,18 +106,18 @@ lua_shared_index(struct lua_State *L)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if (val_type == LUA_TNUMBER) {
 | 
	
		
			
				|  |  |  		double num = lua_tonumber(L_shared, -1);
 | 
	
		
			
				|  |  | -		printf("value: %G\n", num);
 | 
	
		
			
				|  |  |  		lua_pushnumber(L, num);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	} else if (val_type == LUA_TBOOLEAN) {
 | 
	
		
			
				|  |  |  		int i = lua_toboolean(L_shared, -1);
 | 
	
		
			
				|  |  | -		printf("value: %s\n", i ? "true" : "false");
 | 
	
		
			
				|  |  |  		lua_pushboolean(L, i);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	} else if (val_type == LUA_TNIL) {
 | 
	
		
			
				|  |  |  		lua_pushnil(L);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	} else {
 | 
	
		
			
				|  |  |  		size_t len = 0;
 | 
	
		
			
				|  |  |  		const char *str = lua_tolstring(L_shared, -1, &len);
 | 
	
		
			
				|  |  | -		printf("value: %s\n", str);
 | 
	
		
			
				|  |  |  		lua_pushlstring(L, str, len);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -111,6 +129,7 @@ lua_shared_index(struct lua_State *L)
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +/* Write access to shared element (shared.element = x) */
 | 
	
		
			
				|  |  |  static int
 | 
	
		
			
				|  |  |  lua_shared_newindex(struct lua_State *L)
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -118,8 +137,6 @@ lua_shared_newindex(struct lua_State *L)
 | 
	
		
			
				|  |  |  	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");
 | 
	
	
		
			
				|  | @@ -129,37 +146,44 @@ lua_shared_newindex(struct lua_State *L)
 | 
	
		
			
				|  |  |  		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);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		pthread_mutex_lock(&lua_shared_lock);
 | 
	
		
			
				|  |  | +		lua_getglobal(L_shared, "shared");
 | 
	
		
			
				|  |  |  		lua_pushnumber(L_shared, num);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	} else if (key_type == LUA_TBOOLEAN) {
 | 
	
		
			
				|  |  |  		int i = lua_toboolean(L, 2);
 | 
	
		
			
				|  |  | -		printf("index: %s\n", i ? "true" : "false");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		pthread_mutex_lock(&lua_shared_lock);
 | 
	
		
			
				|  |  | +		lua_getglobal(L_shared, "shared");
 | 
	
		
			
				|  |  |  		lua_pushboolean(L_shared, i);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	} else {
 | 
	
		
			
				|  |  |  		size_t len = 0;
 | 
	
		
			
				|  |  |  		const char *str = lua_tolstring(L, 2, &len);
 | 
	
		
			
				|  |  | -		printf("index: %s\n", str);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		if ((len > 1) && (0 == memcmp(str, "__", 2))) {
 | 
	
		
			
				|  |  | +			return luaL_error(L, "shared index is reserved");
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		pthread_mutex_lock(&lua_shared_lock);
 | 
	
		
			
				|  |  | +		lua_getglobal(L_shared, "shared");
 | 
	
		
			
				|  |  |  		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);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -172,6 +196,8 @@ lua_shared_newindex(struct lua_State *L)
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +/* Register the "shared" library in a new Lua state.
 | 
	
		
			
				|  |  | + * Call it once for every Lua state accessing "shared" elements. */
 | 
	
		
			
				|  |  |  void
 | 
	
		
			
				|  |  |  lua_shared_register(struct lua_State *L)
 | 
	
		
			
				|  |  |  {
 |