Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
208 views
in Technique[技术] by (71.8m points)

multithreading - Lua 5.2.2 Broken Threading System

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
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...