thatnks for the look-over, I've noticed you've been using Lua brightly too on moonman.
It is a bit confusing but there is no multi-threading in Lua, so i am not creating new threads, but the api and documentation use the word thread for coroutine (i think it was something that changed somewhere in history..)
lua_resume does some error checking (well it returns a value) and i'm not checking that value the first time (i assume (ouch)) it's ok sine it's just a new thread and i know exactly whats on the stack. i could be checking more.
anyway, after a few days of missing social calls, and not washing myself I do believe i've fixed the problems.
It has to do with the thread/coroutine not being referenced from the lua side, last night i managed to get 250.000 coroutines running (my memory didn't like it much though).
i've cleaned up the code a lot more to isolate the problem, and then fixed it, now i am left with:
SuperStrict
Local manager:TLuaManager = New TLuaManager
manager.initLua()
Graphics 1024,768
Local startmem:Int = GCMemAlloced()
While Not KeyDown(key_escape)
Cls
manager.Update()
If KeyDown(key_space)
For Local i:Int = 0 Until 2000
manager.startCoroutine()
Next
EndIf
Print GCMemAlloced() -startmem
Flip
Wend
Type TCoroutine
Field coroutine:Byte Ptr
Field refID:Int
Function Create:TCoroutine(coroutine:Byte Ptr, refID:Int)
Local ent:TCoroutine = New TCoroutine
ent.coroutine = coroutine
ent.refID = refID
Return ent
EndFunction
EndType
Type TLuaManager
Field state:Byte Ptr
Field coroutines:TList = New TList
Field luaFile:String
Method Update()
DrawText coroutines.count() , 0,0
For Local c:TCoroutine = EachIn coroutines
If (lua_status(c.coroutine) = 1)
If Rand(100)=1
lua_resume(c.coroutine, 0)
EndIf
Else
lua_getfield(state, LUA_GLOBALSINDEX, "ThreadTable")
lua_pushnil(state)
lua_rawseti(state, -2, c.refID)
lua_pop(state, 1) '; /* ThreadTable */
c.coroutine = Null
ListRemove(coroutines,c)
EndIf
Next
If KeyHit(key_d)
Print "global state: "
stackdump(state)
EndIf
If KeyDown(key_x)
closeLua()
initlua()
EndIf
EndMethod
Method initLua()
state = luaL_newstate()
luaL_openlibs(state)
luaFile = LoadText("coroutines.lua")
lua_pushstring(state ,"ThreadTable");
lua_pushvalue(state , LUA_GLOBALSINDEX);
lua_settable(state ,LUA_GLOBALSINDEX);
EndMethod
Method startCoroutine()
Local thread:Byte Ptr
lua_getfield(state, LUA_GLOBALSINDEX, "ThreadTable")
thread = lua_newthread(state)
Local refID:Int = luaL_ref(state, -2);
lua_pop(state,1);
If luaL_dostring(thread, luaFile ) = 1 Then
Local err:String = "Error: "+lua_tostring(thread, -1)
stackDump(thread)
RuntimeError(err)
lua_pop(thread, 1)
lua_close(thread)
EndIf
lua_getglobal(thread , "main") 'Puts the function onto the stack
Local routine:TCoroutine = TCoroutine.Create(thread, refID)
coroutines.addlast(routine)
lua_resume(thread, 0)
EndMethod
Method closeLua()
If state
lua_close(state)
state = Null
Else
Throw("state was null already")
EndIf
EndMethod
Function stackDump(state:Byte Ptr Var)
Local str:String
Local top:Int = lua_gettop(state)
For Local i:Int = 1 To top
Local t:Int = lua_type(state, i)
Select t
Case LUA_TSTRING
str:+ lua_tostring(state, i)
Case LUA_TBOOLEAN
str:+ lua_toboolean(state, i)
Case LUA_TFUNCTION
str:+ "FUNCTION"
Case LUA_TNUMBER
str:+ lua_tonumber(state, i)
Case LUA_TNIL
str:+ "NIL"
Case LUA_TNONE
str:+ "NONE"
Case LUA_TLIGHTUSERDATA
str:+ "LIGHTUSERDATA"
Case LUA_TTABLE
str:+ "TABLE"
Case LUA_TUSERDATA
str:+ "USERDATA"
Case LUA_TTHREAD
str:+ "THREAD"
Default
str:+ lua_typename(state, i)
EndSelect
If i<top
str:+", "
EndIf
Next
Print "stack: "+str
EndFunction
EndType
in the initLua:
lua_pushstring(state ,"ThreadTable");
lua_pushvalue(state , LUA_GLOBALSINDEX);
lua_settable(state ,LUA_GLOBALSINDEX);
creates a global table,
in the startsCoroutine():
lua_getfield(state, LUA_GLOBALSINDEX, "ThreadTable")
thread = lua_newthread(state)
Local refID:Int = luaL_ref(state, -2);
lua_pop(state,1);
saves a refence of the thread in the global table.
in the Update():
lua_getfield(state, LUA_GLOBALSINDEX, "ThreadTable")
lua_pushnil(state)
lua_rawseti(state, -2, c.refID)
lua_pop(state, 1) '; /* ThreadTable */
removes the refence from the table when it's not needed anymore.
pff I hope the reast is easy sailing
ps and on the plus side: this stuff above made me read and re-read the manual, documentation, and mailing lists. So the simpler stuff i've read about too