Commits

Igor Baidiuk  committed eea3d43

Finished fromLua sketch and wrote some comments on the whole module design

  • Participants
  • Parent commits 7f1ed68

Comments (0)

Files changed (2)

 #ifndef __LUA_CHANNELS_HEADER__
 #define __LUA_CHANNELS_HEADER__
 
+/** 
+lua.channels is a module that provides safe means of transporting complex Lua values
+between independent states.
+
+The main concept is a channel - a multiple producer-single consumer queue, that is also
+a Lua userdata to be used from script.
+
+There can be only single receiver point, located in a state where it was originally created
+Contrary, there can be multiple sender points, placed manually in other states or sent via
+channels.
+
+The main idea is when you send original channel via other channel, you'll automatically get
+a receiver endpoint
+
+Limitations:
+0. There's no "peek" and will not be. If you receive message, it's removed from queue.
+
+1. Only non-executable Lua data can be sent over channels; functions and coroutines aren't allowed
+to be sent. This is because saving and restoring full function context is a rather complex task
+
+2. Fat userdata objects should have "__channel__" metamethod to be transferred over channel;
+if metamethod is not found, then sender state receives Lua error.
+
+3. __channel__ should follow contract:
+
+a) serialize values from Lua
+parameter 1: fat userdata to be transferred; it's an object to which metatable is attached
+return 1: standalone clone of original fat userdata as a light userdata
+
+b) deserialize values back to Lua
+parameter 1: light userdata received from serialization stage
+return 1: fat userdata constructed from parameter 1
+notes: incoming light userdata should be deallocated in the process
+
+*/
 #include <lua.h>
 
 #ifdef __cplusplus

File luaVariant.hpp

 			case LUA_TTABLE:
 				{
 					Table t;
+                    lua_checkstack(L, 2);
 					
 					lua_pushnil(L);
 					while (lua_next(L, from))
 				}
 			case LUA_TUSERDATA:
 				{
+                    lua_checkstack(L, 2);
 					Userdata ud;
+                    // check that fat userdata has any means of thransporting it through channel
+                    if ( !luaL_getmetafield(L, from, "__channel__") || !(ud.second = lua_tocfunction(L, -1) ) )
+                        return Variant();
+                    
+                    lua_pushvalue(L, from);
+                    if (lua_pcall(L, 1, 1, 0))
+                        return Variant();
+                    
+                    ud.first = lua_touserdata(L, -1);
+                    lua_pop(L, 1);
 					
 					return Variant(ud);
 				}