//
// 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;
}