Add coroutine support (WIP)

This commit is contained in:
Jérôme Leclercq
2017-06-08 15:53:17 +02:00
parent a8129b218b
commit 01edc4fb21
8 changed files with 154 additions and 16 deletions

View File

@@ -0,0 +1,55 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Lua scripting module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Lua/LuaCoroutine.hpp>
#include <Lua/lauxlib.h>
#include <Lua/lua.h>
#include <Lua/lualib.h>
#include <Nazara/Lua/Debug.hpp>
namespace Nz
{
LuaCoroutine::LuaCoroutine(lua_State* internalState, int refIndex) :
LuaState(internalState),
m_ref(refIndex)
{
}
LuaCoroutine::~LuaCoroutine()
{
if (m_ref >= 0)
DestroyReference(m_ref);
}
bool LuaCoroutine::CanResume() const
{
return lua_status(m_state) == LUA_YIELD;
}
Ternary LuaCoroutine::Resume(unsigned int argCount)
{
LuaInstance& instance = GetInstance(m_state);
if (instance.m_level++ == 0)
instance.m_clock.Restart();
int status = lua_resume(m_state, nullptr, argCount);
instance.m_level--;
if (status == LUA_OK)
return Ternary_True;
else if (status == LUA_YIELD)
return Ternary_Unknown;
else
{
m_lastError = ToString(-1);
Pop();
return Ternary_False;
}
}
bool LuaCoroutine::Run(int argCount, int /*resultCount*/)
{
return Resume(argCount) != Ternary_False;
}
}

View File

@@ -30,7 +30,7 @@ namespace Nz
}
LuaInstance::LuaInstance() :
LuaState(this, lua_newstate(MemoryAllocator, this)),
LuaState(nullptr),
m_memoryLimit(0),
m_memoryUsage(0),
m_timeLimit(1000),

View File

@@ -12,6 +12,7 @@
#include <Nazara/Core/MemoryHelper.hpp>
#include <Nazara/Core/MemoryView.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <Nazara/Lua/LuaCoroutine.hpp>
#include <Nazara/Lua/LuaInstance.hpp>
#include <cstdlib>
#include <stdexcept>
@@ -127,7 +128,6 @@ namespace Nz
LuaState::LuaState(LuaState&& state) noexcept :
m_lastError(state.m_lastError),
m_instance(state.m_instance),
m_state(state.m_state)
{
}
@@ -570,6 +570,14 @@ namespace Nz
lua_xmove(m_state, instance->m_state, n);
}
LuaCoroutine LuaState::NewCoroutine()
{
lua_State* thread = lua_newthread(m_state);
int ref = luaL_ref(m_state, LUA_REGISTRYINDEX);
return LuaCoroutine(thread, ref);
}
bool LuaState::NewMetatable(const char* str)
{
return luaL_newmetatable(m_state, str) != 0;
@@ -783,7 +791,6 @@ namespace Nz
LuaState& LuaState::operator=(LuaState&& state) noexcept
{
m_instance = state.m_instance;
m_lastError = std::move(state.m_lastError);
m_state = state.m_state;
@@ -792,12 +799,14 @@ namespace Nz
bool LuaState::Run(int argCount, int resultCount)
{
if (m_instance->m_level++ == 0)
m_instance->m_clock.Restart();
LuaInstance& instance = GetInstance(m_state);
if (instance.m_level++ == 0)
instance.m_clock.Restart();
int status = lua_pcall(m_state, argCount, resultCount, 0);
m_instance->m_level--;
instance.m_level--;
if (status != 0)
{
@@ -815,12 +824,12 @@ namespace Nz
return lua_upvalueindex(upValue);
}
LuaState LuaState::GetState(lua_State* internalState)
LuaInstance& LuaState::GetInstance(lua_State* internalState)
{
LuaInstance* instance;
lua_getallocf(internalState, reinterpret_cast<void**>(&instance));
return LuaState(instance, internalState);
return *instance;
}
int LuaState::ProxyFunc(lua_State* internalState)