I'm using love.thread to generate a map for my game. It works perfectly - mostly. However, some few times, I am loosing all connectivity to the thread. The thread object is not nil, I get no errors when indexing it to get new data, I just don't get any data.
First, I created a "print" function inside the thread -> all this one does is it sends packets back to the main thread which are then printed to console from the main thread. This works great for debugging, but not in the above case, where the thread seems to be "lost". In this case, I get nothing returned to the main thread.
Next, I tried logging to a file instead from inside the thread. After "loosing" the thread, I get the same output in the file as without loosing it, however, I do not know if this is from this time the thread was created or from the time before, when it ran fine.
This code creates and handles the thread:
As I said, mapGenerateThread does never become nil...
Code: Select all
function map.generate(width, height, seed, tutorialMap)
if not mapGenerateThread then
print("Generating map!")
newMapStarting = true
mapRenderPercent = nil
mapGeneratePercent = nil
numTrains = 0
mapSeed = seed
if not DEDICATED then
console.init(love.graphics.getWidth(),love.graphics.getHeight()/2)
love.graphics.translate(camX + love.graphics.getWidth()/(2*camZ), camY + love.graphics.getHeight()/(2*camZ))
simulation.stop()
loadingScreen.addSection("Generating Map")
end
mapImage,mapShadowImage,mapObjectImage = nil,nil,nil
if not width then width = 4 end
if not height then height = 4 end
if not seed then seed = 1 end
if width < 4 then
print("Minimum width is 4!")
width = 4
end
if height < 4 then
print("Minimum height is 4!")
height = 4
end
if tutorialMap then
print("Generating Map...", tutorialMap.width, tutorialMap.height)
else
print("Generating Map...", width, height)
end
-- mapImage, mapShadowImage, mapObjectImage = map.render()
mapGenerateThread = love.thread.newThread("mapGeneratingThread" .. mapGenerateThreadNumber, "Scripts/mapGenerate.lua")
mapGenerateThreadNumber = mapGenerateThreadNumber + 1
mapGenerateThread:start()
if tutorialMap then mapGenerateThread:set("tutorialMap", TSerial.pack(tutorialMap)) end
mapGenerateThread:set("width", width )
mapGenerateThread:set("height", height )
mapGenerateThread:set("seed", seed )
mapGenerateStatusNum = 0
mapGenerateMsgNumber = 0
prevStr = nil
print("mapGenerateThread", mapGenerateThread)
else
percent = mapGenerateThread:get("percentage")
if percent and loadingScreen then
loadingScreen.percentage("Generating Map", percent)
end
-- first, look for new messages:
str = mapGenerateThread:get("msg" .. mapGenerateMsgNumber)
while str do
print(str, mapGenerateMsgNumber)
if prevStr == str and str == "I'm done!" then
print("same message twice")
love.event.quit()
end
prevStr = str
mapGenerateMsgNumber = incrementID(mapGenerateMsgNumber)
str = mapGenerateThread:get("msg" .. mapGenerateMsgNumber)
end
-- then, check if there was an error:
err = mapGenerateThread:get("error")
if err then
print("MAP GENERATING THREAD error: " .. err)
love.event.quit()
end
status = mapGenerateThread:get("status" .. mapGenerateStatusNum)
if status and loadingScreen then
mapGenerateStatusNum = incrementID(mapGenerateStatusNum)
loadingScreen.addSubSection("Generating Map", status)
end
status = mapGenerateThread:get("status")
if status == "done" then
print("Generating done!")
curMap = TSerial.unpack(mapGenerateThread:demand("curMap"))
curMapRailTypes = TSerial.unpack(mapGenerateThread:demand("curMapRailTypes"))
curMapOccupiedTiles = TSerial.unpack(mapGenerateThread:demand("curMapOccupiedTiles"))
curMapOccupiedExits = TSerial.unpack(mapGenerateThread:demand("curMapOccupiedExits"))
if loadingScreen then
loadingScreen.percentage("Generating Map", 100)
end
map.print("Finished Map:")
mapGenerateThread = nil
if not DEDICATED then
map.render(curMap)
else
sendMap() -- important! send before running the map!
runMap()
end
collectgarbage("collect")
return curMap
-- elseif status and loadingScreen then
-- loadingScreen.addSubSection("Generating Map", status)
end
end
end
Code: Select all
require("love.filesystem")
file = love.filesystem.newFile( "threadLog.txt" )
file:open("w")
file:write("1\n")
thisThread = love.thread.getThread()
package.path = "Scripts/?.lua;" .. package.path
require("mapUtils")
require("TSerial")
require("misc")
local msgNumber = 0
print = function(...)
sendStr = ""
for i = 1, #arg do
if arg[i] then
sendStr = sendStr .. arg[i] .. "\t"
end
end
thisThread:set("msg" .. msgNumber, sendStr)
msgNumber = incrementID(msgNumber)
end
print("2")
file:write("2\n")
print("4")
width = thisThread:demand("width")
file:write("5\n")
print("5")
height = thisThread:demand("height")
seed = thisThread:demand("seed")
tutorialMap = thisThread:get("tutorialMap")
print("6")
file:write("6\n")
if tutorialMap then
tutorialMap = TSerial.unpack(tutorialMap)
width = tutorialMap.width
height = tutorialMap.height
end
print("7")
file:write("7\n")
math.randomseed(seed)
if not tutorialMap then curMap = {width=width, height=height, time=0} end
curMapOccupiedTiles = {}
curMapOccupiedExits = {}
curMapRailTypes = {}
print("8")
file:write("8\n")
thisThread:set("percentage", 0)
for i = 0,width+1 do
if not tutorialMap then curMap[i] = {} end
curMapRailTypes[i] = {}
if i >= 1 and i <= width then
curMapOccupiedTiles[i] = {}
curMapOccupiedExits[i] = {}
for j = 1, height do
curMapOccupiedTiles[i][j] = {}
curMapOccupiedTiles[i][j].from = {}
curMapOccupiedTiles[i][j].to = {}
curMapOccupiedExits[i][j] = {}
end
end
end
print("9")
file:write("9\n")
if not tutorialMap then
--thisThread:set("status", "rails")
threadSendStatus( thisThread,"rails")
thisThread:set("percentage", 10)
generateRailRectangles()
thisThread:set("percentage", 20)
clearLargeJunctions()
thisThread:set("percentage", 30)
connectLooseEnds()
thisThread:set("percentage", 40)
else
curMap = tutorialMap
end
print("10")
file:write("10\n")
calculateRailTypes()
thisThread:set("percentage", 50)
if not tutorialMap then
--thisThread:set("status", "houses")
threadSendStatus( thisThread,"houses")
placeHouses()
thisThread:set("percentage", 60)
--thisThread:set("status", "hotspots")
threadSendStatus( thisThread,"hotspots")
placeHotspots()
thisThread:set("percentage", 70)
end
generateRailList()
thisThread:set("percentage", 90)
-- return the results to parent (main) thread:
thisThread:set("curMap", TSerial.pack(curMap))
thisThread:set("curMapRailTypes", TSerial.pack(curMapRailTypes))
thisThread:set("curMapOccupiedTiles", TSerial.pack(curMapOccupiedTiles))
thisThread:set("curMapOccupiedExits", TSerial.pack(curMapOccupiedExits))
thisThread:set("status", "done")
print("I'm done!")
file:write("Done\n")
return
This is running on the server, headless (no love.graphics initialized) and the server runs fine for a few hours (meaning it generates about 100 or 200 maps before all this thread-loosing happens.