2013-05-09 27 views
3

我發起的Redis連接池redis.lua,由C調用,我得到了一個redis_lua_state,這Lua的狀態是全球發起的一次,其他線程只能從它那裏得到如何在多個Lua狀態(多線程)之間傳遞數據?

雖然總會有一個HTTP請求(工作線程),我需要獲取從redis_lua_state一個Redis的連接,然後又一個新的Lua狀態來加載其他的Lua腳本,這些腳本將使用這個Redis的連接與Redis的溝通,怎麼樣去做這個?或者如何設計我的Lua腳本來簡化它?


代碼示例:

/* on main thread, to init redis pool connection */ 
    lua_State *g_ls = NULL; 
    lua_State *init_redis_pool(void) { 
      int ret = 0; 
      g_ls = luaL_newstate(); 
      lua_State *ls = g_ls; 

      luaL_openlibs(ls); 
      ret = luaL_loadfile(ls, "redis.lua"); 
      const char *err; 
      (void)err; 

      /* preload */ 
      ret = lua_pcall(ls, 0, 0, 0); 

      lua_getglobal(ls, "init_redis_pool"); 
      ret = lua_pcall(ls, 0, 0, 0); 

      return ls; 
    } 

    /* worker thread */ 
    int worker() { 
      ... 
      lua_State *ls = luaL_newstate(); 
      ret = luaL_loadfile(ls, "run.lua"); 

      /* How to fetch data from g_ls? */ 
      ... 
      lua_getglobal(ls, "run") 
      ret = lua_pcall(ls, 0, 0, 0) 

      lua_close(ls); 
      ... 
      return 0; 
    } 

回答

4

如果你的Lua的狀態是不同的,那麼就沒有辦法做到這一點。您的工作線程將不得不初始化Redis連接對其進行處理。

+0

我想我可以維護一個引用Redis池的表,並將表傳遞給工作者的Lua狀態,在連續的Lua腳本中,接受該表作爲參數。 – coanor 2013-05-09 03:42:06

+0

@coanor:如果這是一個Lua表,你不能那樣做。單獨的Lua州*是獨立的*。這些Redis池是Lua userdata,對不對?你不能將Lua userdata傳遞給不同的Lua狀態。 – 2013-05-09 03:43:10

+0

我的意思是把一個表保存爲'lua_pcall'的返回值,那麼這個表的內存在C空間中,然後我將表傳遞給另一個Lua狀態,這是不可能的? – coanor 2013-05-09 03:49:35

4

這樣做的一種方法是在C端Lua狀態之間實現複製變量。我在ERP項目中做了類似的事情,但是它需要一點麻煩,尤其是在複製用戶數據時。

我所做的是實現某種超級全局變量(在我的實例中是一個C類)系統,實現爲全局表的__index__newindex,它是默認Lua全局表的代理。設置全局變量時,__newindex會將其複製到該全局超級變量。當另一個Lua國家試圖訪問這個全球的時候,它會從相同的結構中檢索它。

然後Redis連接可能是一個鎖定共享的互斥鎖,所以當一個狀態訪問它時,另一個不能。

當然,還有訪問Lua默認全局變量的問題,您還需要處理。你可以看看Lua lanes,如果這是一個選項(我沒有Redis的經驗,所以不知道如何打開Lua,但我看到你有完全訪問C api,所以它應該工作)。