当前位置: 首页 > 工具软件 > Safe Lua > 使用案例 >

lua不同虚拟机共享table的实现2 - 通过自定义c对象共享

姚和顺
2023-12-01
//
//  main.cpp
//  lua
//
//  Created by ycmac on 2020/12/14.
//  Copyright © 2020 ycmac. All rights reserved.
//

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <thread>
#include <vector>
#include <list>
#include <map>

#include "../../src/lua.hpp"


extern "C"
{
    #include "cjson/lua_cjson.h"

    #include "../../src/ltable.h"
    #include "../../src/lobject.h"
    #include "../../src/lstate.h"
    #include "../../src/lgc.h"
    #include "../../src/lapi.h"
    #include "../../src/lstring.h"
    #include "../../src/lvm.h"
}



typedef union UKey
{
    lua_Integer n;
    char* str;

} UKey;

typedef union UValue
{
    lua_Integer n;
    char* str;
    double f = 0.0;
    bool b;
    void* p;
} UValue;


enum class TypeV : char
{
    T_INT = 0,
    T_STR,
    T_DOUBLE,
    T_BOOL,
    T_TABLE,
    T_NIL,
};


typedef struct CKey
{
    UKey key;
    TypeV type;
} CKey;

struct CValue
{
    UValue value;
    TypeV  type;
};


struct CTable
{
    std::map<CKey*, CValue*> valueList;
    
};



std::mutex shareTableMutex;
std::list<CTable*> sharedTableList;



void saveAsCTable(lua_State* L, CTable* tb)
{
    int top = lua_gettop(L);
    lua_pushnil(L);
    while(lua_next(L, -2) != 0)
    {
        CKey* nKey = new CKey;  CValue* nValue = new CValue;
        
        int keytype = lua_type(L, -2);
        if (keytype == LUA_TNUMBER)
        {
            nKey->key.n = lua_tointegerx(L, -2, NULL);
            nKey->type = TypeV::T_INT;
        }
        else if(keytype == LUA_TSTRING)
        {
            const char* str;  size_t len;
            str = lua_tolstring(L, -2, &len);
            nKey->key.str = (char*)malloc(len + 1);
            memcpy(nKey->key.str, str, len);
            nKey->key.str[len] = '\0';
            nKey->type = TypeV::T_STR;
        }
        else
        {
            printf("unknow key type\n");
        }

        int valueType = lua_type(L, -1);
        if (valueType == LUA_TNUMBER)
        {
            int isNum = 0;
            nValue->value.n = lua_tointegerx(L, -1, &isNum);
            if (isNum)
            {
                nValue->type = TypeV::T_INT;
            }
            else
            {
                nValue->value.f = lua_tonumber(L, -1);
                nValue->type = TypeV::T_DOUBLE;
            }
        }
        else if(valueType == LUA_TSTRING)
        {
            const char* str;  size_t len;
            str = lua_tolstring(L, -1, &len);
            nValue->value.str = (char*)malloc(len + 1);
            memcpy(nValue->value.str, str, len);
            nValue->value.str[len] = '\0';
            nValue->type = TypeV::T_STR;
        }
        else if(valueType == LUA_TBOOLEAN)
        {
            bool value = lua_toboolean(L, -1);
            nValue->value.b = value;
            nValue->type = TypeV::T_BOOL;
          
        }
        else if(valueType == LUA_TNIL)
        {
            nValue->value.p = nullptr;
            nValue->type = TypeV::T_NIL;
        }
        else if(valueType == LUA_TTABLE)
        {
            CTable* nTable = new CTable;
            nValue->value.p = nTable;
            nValue->type = TypeV::T_TABLE;
            saveAsCTable(L, nTable);
        }
        else
        {
            printf("Invalade value type, not support");
            nValue->value.p = nullptr;
            nValue->type = TypeV::T_NIL;
        }
      
        tb->valueList.insert(std::make_pair(nKey, nValue));
        lua_pop(L, 1);
    }
    int top2 = lua_gettop(L);
    if(top2 - top > 0)
    {
        lua_pop(L, top2 - top);
    }

    
}


unsigned long long totalTime = 0;

//将CTable存储到lua表,并且释放CTable的内存
void saveCTableToLua(lua_State* L, CTable* tb)
{
    if (tb == nullptr) { return ;}
    
    std::map<CKey*, CValue*>::iterator it = tb->valueList.begin();
    for (; it != tb->valueList.end(); ++it)
    {
        CKey* ckey = it->first;
        CValue* cvalue = it->second;
        if (ckey->type == TypeV::T_INT)
        {
            lua_pushinteger(L, ckey->key.n);
        }
        else if(ckey->type == TypeV::T_STR)
        {
            lua_pushstring(L, ckey->key.str);
           // free(ckey->key.str);
        }
        else
        {
            printf("unknow error\n");
        }

        
        if(cvalue->type == TypeV::T_STR)
        {
             lua_pushstring(L, cvalue->value.str);
             // free(cvalue->value.str);
        }
        else if (cvalue->type == TypeV::T_INT)
        {
             lua_pushinteger(L, cvalue->value.n);
        }
        else if(cvalue->type == TypeV::T_DOUBLE)
        {
            lua_pushnumber(L, cvalue->value.f);
        }
        else if(cvalue->type == TypeV::T_TABLE)
        {
           lua_newtable(L);
           CTable* nTable = (CTable*)cvalue->value.p;
           saveCTableToLua(L, nTable);
        }
        else if(cvalue->type == TypeV::T_BOOL)
        {
            lua_pushboolean(L, cvalue->value.b);
        }
        else if(cvalue->type == TypeV::T_NIL)
        {
            lua_pushnil(L);
        }
        else
        {
            printf("Invalade value type, not support");
            lua_pushnil(L);
        }
        
        lua_settable(L, -3);
      //  delete ckey;
      //  delete cvalue;
    }
    
  //  tb->valueList.clear();
  //  delete tb;

}



lua_State* Lvm1 = nullptr;
void createSceondVM()
{

   Lvm1 = luaL_newstate();
   luaL_openlibs(Lvm1);
   luaopen_cjson_safe(Lvm1);
   lua_setglobal(Lvm1, "cjson");
    
   if (luaL_dofile(Lvm1,"share2.lua") != 0)
   {
       printf("Load Lua File Error\n");
   }
  
    //清空栈才会GC
    lua_pop(Lvm1, lua_gettop(Lvm1));
    
    int task = 1000;
    
    FILE* fp = fopen("/Users/ycmac/Documents/jsondata.txt", "rb");
    size_t len = 0; int total = 0;
    char* content = new char[1024 * 1024];
    len = fread(content + total, sizeof(char), 1024, fp);
    while ( len > 0)
    {
        total += len;
        len = fread(content + total, sizeof(char), 1024, fp);
    }
    fclose(fp);
         
    
    while(true)
    {
 
        int n = lua_gettop(Lvm1);

        if(task > 0)
        {
            task -= 1;

            lua_getglobal(Lvm1, "cjson");
            lua_getfield(Lvm1, -1, "decode");
            lua_pushlstring(Lvm1, content, total);
            lua_call(Lvm1, 1, 1);
            if (lua_istable(Lvm1, -1))
            {
                CTable* shareTable = new CTable;
                saveAsCTable(Lvm1, shareTable);
                shareTableMutex.lock();
                sharedTableList.push_back(shareTable);
                shareTableMutex.unlock();
                
                lua_pop(Lvm1, 1);
            }
            else
            {
                printf("json decode failed\n");
            }
        }
        
    
        int n2 = lua_gettop(Lvm1);
        if(n2 - n > 0)
        {
            lua_pop(Lvm1, n2 - n);
        }
         
        lua_gc(Lvm1, LUA_GCCOLLECT, 0);
    
        
       // sleep(1);
    }
      
   lua_close(Lvm1);  //关闭虚拟机
   
}




static int getSharedTable(lua_State *L)
{
    //clock_t be = clock();
    unsigned long long be = clock_gettime_nsec_np(_CLOCK_REALTIME);
    
    int top = lua_gettop(L);
    CTable* shareTable = nullptr;
    shareTableMutex.lock();
    if(sharedTableList.size() > 0)
    {
        //总是从前面开始取,防止数据包错乱
        shareTable = sharedTableList.front();
        sharedTableList.pop_front();
    }
    shareTableMutex.unlock();
    
    if(shareTable != nullptr)
    {
        lua_newtable(L);
        lua_pushstring(L, "_s");
        lua_pushstring(L, "_s");
        lua_settable(L, -3);
        saveCTableToLua(L, shareTable);
    }
    else
    {
        //新建一个空表放在栈顶
        lua_newtable(L);
    }
    
    int top2 = lua_gettop(L);
    if(top2 - top >= 1)
    {
        lua_pop(L, top2 - top - 1);
    }
    else
    {
        printf("unknow errro2!\n");
    }
    
    //clock_t ed = clock();
    unsigned long long ed = clock_gettime_nsec_np(_CLOCK_REALTIME);
    totalTime += (ed - be);
    
    return 1;
}






int main2()
{
    
    lua_State* L = luaL_newstate();
    std::thread t(&createSceondVM);
    luaL_openlibs(L);
    luaopen_cjson_safe(L);
    lua_setglobal(L, "cjson");
    lua_pushcfunction(L, getSharedTable);
    lua_setglobal(L, "getShareTable");
    if (luaL_dofile(L,"share2.lua") != 0)
    {
        printf("Load Lua File Error\n");
    }

   // clock_t begin = clock();
    unsigned long long begin = clock_gettime_nsec_np(_CLOCK_REALTIME);
    
    bool finish = false;

    while (true)
    {
        int top = lua_gettop(L);
        lua_getglobal(L, "update1");
        if(  lua_isfunction(L, -1) )
        {
            lua_call(L, 0, 0);
        }
      
        lua_getglobal(L, "task");
        if (lua_isnumber(L, -1))
        {
            int task = lua_tointegerx(L, -1, NULL);
            if (task >= 1000 && !finish)
            {
                finish = true;
                //clock_t endtime = clock();
                unsigned long long endtime = clock_gettime_nsec_np(_CLOCK_REALTIME);
                unsigned long long t = endtime - begin;
                printf("task:%d  time: %llu\n", task, t);
                printf("task:%d  time: %llu\n", task, totalTime);
            }
        }
        else
        {
            
            printf("unknow error, task not a number\n");
            
        }
        lua_pop(L, 1);
            
        lua_gc(L, LUA_GCCOLLECT, 0);
        
        int top2 = lua_gettop(L);
        if (top2 - top > 0)
        {
            lua_pop(L, top2 - top);
        }
        
       // sleep(1);
    }
    
    lua_close(L);  //关闭虚拟机
    
    return 0;
    
}




int main()
{
    
    lua_State* L = luaL_newstate();

    luaL_openlibs(L);
    luaopen_cjson_safe(L);
    lua_setglobal(L, "cjson");
    lua_pushcfunction(L, getSharedTable);
    lua_setglobal(L, "getShareTable");
    if (luaL_dofile(L,"share2.lua") != 0)
    {
       printf("Load Lua File Error\n");
    }
    unsigned long long begin = clock_gettime_nsec_np(_CLOCK_REALTIME);
    
    
    bool finish = false;

    
    int task = 1000;


    while (true)
    {
        
         if(task > 0)
         {
             task -= 1;

             FILE* fp = fopen("/Users/ycmac/Documents/jsondata.txt", "rb");
             size_t len = 0; int total = 0;
             char* content = new char[1024 * 1024];
             len = fread(content + total, sizeof(char), 1024, fp);
             while ( len > 0)
             {
                total += len;
                len = fread(content + total, sizeof(char), 1024, fp);
             }
             fclose(fp);
             
             
             lua_getglobal(L, "cjson");
             lua_getfield(L, -1, "decode");
             lua_pushlstring(L, content, total);
             lua_call(L, 1, 1);
             if (lua_istable(L, -1))
             {
                 lua_getglobal(L, "update2");
                 if( lua_isfunction(L, -1) )
                 {
                     lua_pushvalue(L, -2);
                     lua_call(L, 1, 0);
                 }
                 lua_pop(L, 1);
             }
             else
             {
                 printf("json decode failed\n");
             }
             
         }

       lua_getglobal(L, "task");
       if (lua_isnumber(L, -1))
       {
           int task = lua_tointegerx(L, -1, NULL);
           if (task >= 1000 && !finish)
           {
               finish = true;
               //clock_t endtime = clock();
               unsigned long long endtime = clock_gettime_nsec_np(_CLOCK_REALTIME);
               unsigned long long t = endtime - begin;
               printf("task:%d  time: %llu\n", task, t);
           }
       }
       else
       {
           
           printf("unknow error, task not a number\n");
           
       }
       lua_pop(L, 1);
           
       lua_gc(L, LUA_GCCOLLECT, 0);
       
      // sleep(1);
    }
       
    lua_close(L);  //关闭虚拟机
       
    return 0;
    
}

 

 

 

 

 

 类似资料: