Lua 5.2.2 Broken Threading System

青春壹個敷衍的年華 提交于 2019-12-13 22:45:27

问题


Ey,

I'm making threading system in lua and I have a crash when I resume a lot threads... I'm noob in C Lua and I don't really know what is the good or bad what I'm doing in the next codes...

I flagged crash places with "//maybe here"

#include<cstdio>
#include<ala_lua.h>

extern"C"{
    void __stdcall Sleep(unsigned long);
};



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

    lua_State*T=lua_newthread(L);
    luaL_loadfile(T,"c:/clua.lua");
    co_resume(T);

    do{
        Sleep(1);
    }while(co_update());

    lua_close(L);

    gets(new char[1]);
    return 0;
};

#ifndef ALA_LUA_H
#define ALA_LUA_H

#include<ala_lua_co.h>

void luaA_libs(lua_State*);

static int luaA_sleep(lua_State*handle){
    co_sleep(handle,lua_tointeger(handle,1));
    return 0;
};

static int luaA_rthread(lua_State*handle){
    if(lua_isthread(handle,1)){
        co_resume(lua_tothread(handle,1));
    };
    return 0;
};

static int luaA_mthread(lua_State*handle){
    if(lua_isfunction(handle,1)){
        lua_State*thread=lua_newthread(handle);

        lua_pushvalue(handle,1);
        lua_xmove(handle,thread,1);

        return 1;
    };
    return 0;
};

void luaA_libs(lua_State*handle){
    lua_register(handle,"mthread",luaA_mthread);
    lua_register(handle,"rthread",luaA_rthread);
    lua_register(handle,"sleep",luaA_sleep);
};

#endif

#ifndef ALA_LUA_CO_H
#define ALA_LUA_CO_H

#include<vector>
#include<time.h>
#include<stdio.h>
#include<cstring>
#include<lua.hpp>

std::vector<lua_State*>co_threads;
std::vector<time_t*>co_threads_delay;

static const size_t CO_NPOS=-1;

bool co_update();
size_t co_new(lua_State*);
size_t co_get(lua_State*);
void co_resume(lua_State*);
void co_report(lua_State*);
void co_rem(lua_State*,size_t);
void co_sleep(lua_State*,time_t);
void co_remifdead(lua_State*,size_t);



void co_remifdead(lua_State*handle,size_t index=CO_NPOS){
    switch(lua_status(handle)){
        case LUA_OK:{
            if(lua_gettop(handle)==0)co_rem(handle,index);
            return;
        };
        case LUA_ERRRUN:{
            co_rem(handle,index);
            return;
        };
    };
};

void co_rem(lua_State*handle,size_t index=CO_NPOS){
    if(index==CO_NPOS){
        index=co_get(handle);
    };
    if(index!=CO_NPOS){
        co_threads.erase(co_threads.begin()+index);
        delete[]co_threads_delay[index];
        co_threads_delay.erase(co_threads_delay.begin()+index);
    };
};

bool co_update(){
    if(co_threads.empty())return false;
    size_t i=co_threads.size();
    while(i>0){
        --i;

        lua_State*handle=co_threads[i];
        if(lua_status(handle)==LUA_YIELD){
            if(*co_threads_delay[i]<=clock()){
                lua_resume(handle,NULL,0);//here maybe
                co_remifdead(handle,i);
            };
        }else{
            co_remifdead(handle,i);
        };
    };
    return!co_threads.empty();
};

void co_resume(lua_State*handle){
    switch(lua_status(handle)){
        case LUA_YIELD:{
            lua_resume(handle,NULL,0);
            co_remifdead(handle);
            return;
        };
        case LUA_OK:{
            if(lua_gettop(handle)!=0){
                size_t index=co_new(handle);
                lua_resume(handle,NULL,0);//here maybe
                co_remifdead(handle,index);
                return;
            }else{return;};
        };
        default:{return;};
    };
};

void co_sleep(lua_State*handle,time_t slp){
    size_t index=co_get(handle);
    if(index!=CO_NPOS){
        *co_threads_delay[index]=slp+clock();
        lua_yield(co_threads[index],0);
    };
};

void co_report(lua_State*handle){
    if(lua_status(handle)==LUA_ERRRUN){
        const char*error=lua_tostring(handle,-1);
        #ifdef ALA_LUA_ERRLOG
            FILE*file=fopen(ALA_LUA_ERRLOG,"a");
                fputs(error,file);
            fclose(file);
        #else
            puts(error);
        #endif
        lua_pop(handle,-1);
    };
};

size_t co_get(lua_State*handle){
    if(co_threads.empty())return CO_NPOS;
    const size_t l=co_threads.size();
    for(size_t i=0;i<l;++i){
        if(co_threads[i]==handle)return i;
    };
    return CO_NPOS;
};

size_t co_new(lua_State*handle){
    if(lua_status(handle)==LUA_OK&&lua_gettop(handle)!=0){
        time_t*tm=new time_t[1];
        co_threads.push_back(handle);
        co_threads_delay.push_back(tm);
        return co_threads.size()-1;
    };
    return CO_NPOS;
};

#endif

回答1:


Lua has no built-in support for multithreading at the OS level. Lua threads are coroutines, not OS threads. You cannot use Lua threads of the same mother state in different OS threads. You can use separate Lua states in different OS threads but any data exchange between two states must be managed manually.

On the other hand, you can build Lua to support OS-level multithreading by defining lock and unlock macros but these will be called every time the app goes into and leaves Lua.



来源:https://stackoverflow.com/questions/17817452/lua-5-2-2-broken-threading-system

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!