C++ Lua:我的多任务实用程序上的Bug

C++ Lua:我的多任务实用程序上的Bug,c++,c++11,lua,multitasking,embedded-script,C++,C++11,Lua,Multitasking,Embedded Script,我在制作一个利用Lua中多任务系统的类时遇到了问题。 这个类应该能够使用Lua的协同程序系统同时运行多个函数 我想在宿主代码和Lua代码中编写该类的理想用法 在主机代码中 我希望我展示的示例能够在Lua代码中运行指定给“run_task”的函数,就像它们在多任务系统中一样 然后我展示了“类任务系统”的实现。对不起,此代码有点长 #include <list> #include <boost/range/algorithm_ext/erase.hpp> class Task

我在制作一个利用Lua中多任务系统的类时遇到了问题。 这个类应该能够使用Lua的协同程序系统同时运行多个函数

我想在宿主代码和Lua代码中编写该类的理想用法

在主机代码中 我希望我展示的示例能够在Lua代码中运行指定给“run_task”的函数,就像它们在多任务系统中一样

然后我展示了“类任务系统”的实现。对不起,此代码有点长

#include <list>
#include <boost/range/algorithm_ext/erase.hpp>
class TaskSystem
    {
    private:
        lua_State* main_thread;
        struct Task
        {
            lua_State* thread;
            ThreadStatus status;
            bool to_continue(void) const {return status == LUA_YIELD; }
        };
        using TaskList = std::list<Task>;
        TaskList task_list;
        static int run_task(lua_State* _parent)
        {
            //coroutine.create(func)
            lua_getglobal(_parent, "coroutine");
            lua_getfield(_parent, -1, "create");
            lua_pushvalue(_parent, 1); //argument
            lua_pcall(_parent, 1, 1, 0);

            //Converte coroutine into thread object.
            auto co{lua_tothread(_parent, -1)};

            lua_settop(_parent, 0);

            //Register the coroutine.
            auto& task_list{*static_cast<TaskList*>(lua_touserdata(_parent, lua_upvalueindex(1)))};
            task_list.push_back({co, lua_resume(co, nullptr, 0)});

            return 0;
        }
    public:
        TaskSystem(void) :main_thread(nullptr), task_list(){}
        //Enable multitasking.
        TaskSystem(lua_State* _main_thread)
        {
            initialize(_main_thread);
        }
        //Enable multitasiking in the thread.
        void initialize(lua_State* _main_thread)
        {
            if (!_main_thread)
            {
                throw std::runtime_error("TaskSystem must be initialized by valid thread.");
            }

            main_thread = _main_thread;
            lua_pushlightuserdata(main_thread, &task_list); //Task list as upvalue.
            lua_pushcclosure(main_thread, &run_task, 1);
            lua_setglobal(main_thread, "run_task");
        }
        //Resume all tasks.
        void resume_all(void)
        {
            //Remove all threads not resumable.
            //'boost::remove_erase_if' is the function splicing the container(1st arg) according to the lambda(2nd arg).
            boost::remove_erase_if(task_list, [](const Task& _t) {return !_t.to_continue(); });

            //Resume all thread on the list.
            for (auto& t : task_list)
            {
                if (t.to_continue())
                {
                    t.status = lua_resume(t.thread, nullptr, 0);
                }
            }
        }
        //Return the number of the tasks.
        std::size_t count(void) const { return task_list.size(); }
    };
#包括
#包括
班级作业制
{
私人:
lua_状态*主线程;
结构任务
{
lua_状态*线程;
状态;
bool to_continue(void)const{return status==LUA_YIELD;}
};
使用TaskList=std::list;
任务列表任务列表;
静态整型运行任务(lua\U状态*\U父级)
{
//coroutine.create(func)
lua_getglobal(_parent,“coroutine”);
lua_getfield(_parent,-1,“create”);
lua_pushvalue(_parent,1);//参数
lua_pcall(_parent,1,1,0);
//将协程转换为线程对象。
auto-co{lua_-tothread(_-parent,-1)};
lua_settop(_parent,0);
//注册协同程序。
自动和任务列表{*static_cast(lua_-toserdata(_-parent,lua_-upvalueindex(1)))};
任务列表。推回({co,lua_resume(co,nullptr,0)});
返回0;
}
公众:
TaskSystem(void):主线程(nullptr),任务列表(){}
//启用多任务处理。
任务系统(lua_状态*_主线程)
{
初始化(主线程);
}
//在线程中启用多线程。
无效初始化(lua\U状态*\U主线程)
{
如果(!\u主线程)
{
抛出std::runtime_错误(“TaskSystem必须由有效线程初始化”);
}
主线程=_主线程;
lua_pushlightuserdata(主线程和任务列表);//任务列表为upvalue。
lua_pushcclosure(主线程和运行任务,1);
lua_setglobal(主线程,“运行任务”);
}
//恢复所有任务。
作废全部(作废)
{
//移除所有不可恢复的螺纹。
//“boost::remove_erase_if”是根据lambda(第二个参数)拼接容器(第一个参数)的函数。
boost::remove_erase_if(task_list,[](const task&_t){return!\u t.to_continue();});
//恢复列表上的所有线程。
用于(自动&t:任务列表)
{
if(t.to_continue())
{
t、 状态=lua_resume(t.thread,nullptr,0);
}
}
}
//返回任务数。
std::size_t count(void)const{return task_list.size();}
};
让我困惑的问题是,当您尝试运行此代码时,“TaskSystem::resume_all”引发未知异常

当任务数为24或更大时,会引发异常

我曾经认为stackoverflow发生在Lua环境中,但即使我通过“Lua_checkstack”扩展堆栈大小,也会引发异常

如果有人注意到这个决议,请帮助我

我的环境

Lua版本:5.2.4

IDE/编译器:微软visual studio社区2015

宿主代码语言:C++14

修订守则
类任务系统
{
私人:
使用ThreadRef=decltype(luaL_ref(nullptr,0));
lua_状态*主线程;
结构任务
{
螺纹参考螺纹;
状态;
bool to_continue(void)const{return status==LUA_YIELD;}
};
使用TaskList=std::list;
任务列表任务列表;
静态整型运行任务(lua\U状态*\U父级)
{
//coroutine.create(func)
lua_getglobal(_parent,“coroutine”);
lua_getfield(_parent,-1,“create”);
lua_pushvalue(_parent,1);//参数
lua_pcall(_parent,1,1,0);
//co是对线程对象的引用。
auto co{luaL\u ref(_parent,LUA\u registeryindex)};
//注册协同程序。
自动和任务列表{*static_cast(lua_-toserdata(_-parent,lua_-upvalueindex(1)))};
任务列表。推回({co,LUA\u YIELD});
返回0;
}
公众:
TaskSystem(void):主线程(nullptr),任务列表(){}
//启用多任务处理。
任务系统(lua_状态*_主线程)
{
初始化(主线程);
}
//在线程中启用多线程。
无效初始化(lua\U状态*\U主线程)
{
如果(!\u主线程)
{
抛出std::runtime_错误(“TaskSystem必须由有效线程初始化”);
}
主线程=_主线程;
lua_pushlightuserdata(主线程和任务列表);//任务列表为upvalue。
lua_pushcclosure(主线程和运行任务,1);
lua_setglobal(主线程,“运行任务”);
}
//恢复所有任务。
作废全部(作废)
{
//移除所有不可恢复的螺纹。
boost::remove_erase_if(task_list,[](const task&_t){return!\u t.to_continue();});
//恢复列表上的所有线程。
用于(自动&t:任务列表)
{
//获取线程对象,
lua_rawgeti(主线程、lua_注册表索引、t线程);
自动线程{lua_-tothread(主线程,-1)};
//就叫它吧。
t、 状态=lua_resume(线程,空ptr,0);
//如果线程的生命期结束,则禁用对线程的引用。
如果(!t.to_continue()){luaL_unref(主线程,LUA_注册表索引,t.thread);}
}
}
//返回任务数。
std::size_t count(void)const{return task_list.size();}
}

Lua协程将接受垃圾收集。
lua\u settop(\u parent,0)删除对您刚刚创建的协同程序的唯一引用,因此它将被收集
--30 tasks run parallel.
--'run_task' creates coroutine from the function given,
-- and registers it to  the list of coroutines in the host code.
for i = 0, 30 do
    run_task
    (
    function()
        while true do
            print(i) 
            coroutine.yield()
        end
    end
    )
end
#include <list>
#include <boost/range/algorithm_ext/erase.hpp>
class TaskSystem
    {
    private:
        lua_State* main_thread;
        struct Task
        {
            lua_State* thread;
            ThreadStatus status;
            bool to_continue(void) const {return status == LUA_YIELD; }
        };
        using TaskList = std::list<Task>;
        TaskList task_list;
        static int run_task(lua_State* _parent)
        {
            //coroutine.create(func)
            lua_getglobal(_parent, "coroutine");
            lua_getfield(_parent, -1, "create");
            lua_pushvalue(_parent, 1); //argument
            lua_pcall(_parent, 1, 1, 0);

            //Converte coroutine into thread object.
            auto co{lua_tothread(_parent, -1)};

            lua_settop(_parent, 0);

            //Register the coroutine.
            auto& task_list{*static_cast<TaskList*>(lua_touserdata(_parent, lua_upvalueindex(1)))};
            task_list.push_back({co, lua_resume(co, nullptr, 0)});

            return 0;
        }
    public:
        TaskSystem(void) :main_thread(nullptr), task_list(){}
        //Enable multitasking.
        TaskSystem(lua_State* _main_thread)
        {
            initialize(_main_thread);
        }
        //Enable multitasiking in the thread.
        void initialize(lua_State* _main_thread)
        {
            if (!_main_thread)
            {
                throw std::runtime_error("TaskSystem must be initialized by valid thread.");
            }

            main_thread = _main_thread;
            lua_pushlightuserdata(main_thread, &task_list); //Task list as upvalue.
            lua_pushcclosure(main_thread, &run_task, 1);
            lua_setglobal(main_thread, "run_task");
        }
        //Resume all tasks.
        void resume_all(void)
        {
            //Remove all threads not resumable.
            //'boost::remove_erase_if' is the function splicing the container(1st arg) according to the lambda(2nd arg).
            boost::remove_erase_if(task_list, [](const Task& _t) {return !_t.to_continue(); });

            //Resume all thread on the list.
            for (auto& t : task_list)
            {
                if (t.to_continue())
                {
                    t.status = lua_resume(t.thread, nullptr, 0);
                }
            }
        }
        //Return the number of the tasks.
        std::size_t count(void) const { return task_list.size(); }
    };
class TaskSystem
{
private:
    using ThreadRef = decltype(luaL_ref(nullptr, 0));
    lua_State* main_thread;
    struct Task
    {
        ThreadRef thread;
        ThreadStatus status;
        bool to_continue(void) const {return status == LUA_YIELD; }
    };
    using TaskList = std::list<Task>;
    TaskList task_list;
    static int run_task(lua_State* _parent)
    {
        //coroutine.create(func)
        lua_getglobal(_parent, "coroutine");
        lua_getfield(_parent, -1, "create");
        lua_pushvalue(_parent, 1); //argument
        lua_pcall(_parent, 1, 1, 0);

        //co is reference to the thread object.
        auto co{luaL_ref(_parent, LUA_REGISTRYINDEX)};

        //Register the coroutine.
        auto& task_list{*static_cast<TaskList*>(lua_touserdata(_parent, lua_upvalueindex(1)))};
        task_list.push_back({co, LUA_YIELD});

        return 0;
    }
public:
    TaskSystem(void) :main_thread(nullptr), task_list(){}
    //Enable multitasking.
    TaskSystem(lua_State* _main_thread)
    {
        initialize(_main_thread);
    }
    //Enable multitasiking in the thread.
    void initialize(lua_State* _main_thread)
    {
        if (!_main_thread)
        {
            throw std::runtime_error("TaskSystem must be initialized by valid thread.");
        }

        main_thread = _main_thread;
        lua_pushlightuserdata(main_thread, &task_list); //Task list as upvalue.
        lua_pushcclosure(main_thread, &run_task, 1);
        lua_setglobal(main_thread, "run_task");
    }
    //Resume all tasks.
    void resume_all(void)
    {
        //Remove all threads not resumable.
        boost::remove_erase_if(task_list, [](const Task& _t) {return !_t.to_continue(); });

        //Resume all thread on the list.
        for (auto& t : task_list)
        {
            //Get thread object,
            lua_rawgeti(main_thread, LUA_REGISTRYINDEX, t.thread);
            auto thread{ lua_tothread(main_thread, -1) };
            //and call it.
            t.status = lua_resume(thread, nullptr, 0);
            //Disable referenct to the thread if its life-time ended.
            if(!t.to_continue()){luaL_unref(main_thread, LUA_REGISTRYINDEX, t.thread);}
        }
    }
    //Return the number of the tasks.
    std::size_t count(void) const { return task_list.size(); }
}