Am I doing something silly here that means the callback within the coroutine isn’t being called?
I don’t think it’s a garbage collection issue.
I have a feeling it may be an issue with how the callback is called when the callback is inside a coroutine?
function setup()
-- Works
print("Downloading on main thread")
http.request("https://baconipsum.com/api/?type=meat-and-filler¶s=5&format=text", function(data)
print("Main thread request done.")
end)
-- Does not work
local co = coroutine.create(function()
print("Downloading on coroutine thread")
http.request("https://baconipsum.com/api/?type=meat-and-filler¶s=5&format=text", function(data)
print("Coroutine request done.")
end)
end)
coroutine.resume(co)
end
-- Does not work
local co = coroutine.create(function()
print("Downloading on coroutine thread")
http.request("https://baconipsum.com/api/?type=meat-and-filler¶s=5&format=text", function(data)
print("Coroutine request done.")
end)
end)
print(coroutine.status(co))
coroutine.resume(co)
print(coroutine.status(co))
You will find, as @RonJeffries said, that co is dead.
This still doesn’t work even though the coroutine is just suspended instead.
function setup()
-- Works
print("Downloading on main thread")
http.request("https://baconipsum.com/api/?type=meat-and-filler¶s=5&format=text", function(data)
print("Main thread request done.")
end)
-- Does not work
local co = coroutine.create(function()
print("Downloading on coroutine thread")
http.request("https://baconipsum.com/api/?type=meat-and-filler¶s=5&format=text", function(data)
t = data
end)
coroutine.yield()
end)
print(coroutine.status(co))
coroutine.resume(co)
print(coroutine.status(co))
end
function draw()
print(t)
end
@Simeon Is there something odd going on in the backend that would cause the callback to never be called at all?
the coroutine runs, it’s the data that is not return from the http request
function setup()
t = ""
local co = coroutine.create(function()
print("Downloading on coroutine thread")
http.request("https://baconipsum.com/api/?type=meat-and-filler¶s=5&format=text", function(data)
print("success")
t = data
end, function () print("failed") end )
--coroutine.yield()
end)
print(coroutine.status(co))
coroutine.resume(co)
print(coroutine.status(co))
end
function draw()
print(t)
end
my guess is once the coroutine runs the reference to the pass or fail functions is deleted, this must happen somewhere in the http.request function because i tested using a global reference function in pass and fail and it still does not work
-- Use this function to perform your initial setup
function setup()
t = ""
pass = function(data)
print("success")
t = data
end
fail = function ()
print("failed")
end
local co = coroutine.create(function()
print("Downloading on coroutine thread")
http.request("https://baconipsum.com/api/?type=meat-and-filler¶s=5&format=text", pass, fail )
--coroutine.yield()
end)
print(coroutine.status(co))
coroutine.resume(co)
print(coroutine.status(co))
--print("Downloading in setup")
--http.request("https://baconipsum.com/api/?type=meat-and-filler¶s=5&format=text", pass, fail )
end
function draw()
print(t)
end
i’m also inclined to believe the issue is with .request because i use coroutine as thread to load my scenes behind a loading screen and have never seen a callback fail
@skar After a little more digging I believe the issue could potentially stem from native side.
When the native side calls the callback It’ll be using lua_pcall, passing in the lua_State* but by the look of it, coroutines use a different lua_State object.
@Simeon this along the right lines? I’m guessing blindly here.
that’s deeper than my knowledge but what i can say is if you replace http.request with something else that uses callbacks like tween it works as expected
-- Use this function to perform your initial setup
function setup()
t = ""
pass = function(data)
print("success")
t = data
end
fail = function ()
print("failed")
end
local co = coroutine.create(function()
--print("Downloading on coroutine thread")
--http.request("https://baconipsum.com/api/?type=meat-and-filler¶s=5&format=text", pass, fail )
--coroutine.yield()
tween (2, {}, {}, nil, function () print ("tween done") end)
end)
print(coroutine.status(co))
coroutine.resume(co)
print(coroutine.status(co))
--print("Downloading in setup")
--http.request("https://baconipsum.com/api/?type=meat-and-filler¶s=5&format=text", pass, fail )
end
function draw()
print(t)
end
you can piggy back into the tween end function and pass data there, it’s a bit of a hack but it works
-- Use this function to perform your initial setup
function setup()
t = ""
pass = function(data)
print("success")
t = data
end
fail = function ()
print("failed")
end
local co = coroutine.create(function()
print("Downloading on coroutine thread")
tween (2, {}, {}, nil, function ()
http.request("https://baconipsum.com/api/?type=meat-and-filler¶s=5&format=text", pass, fail )
end)
coroutine.yield()
end)
print(coroutine.status(co))
coroutine.resume(co)
print(coroutine.status(co))
--print("Downloading in setup")
--http.request("https://baconipsum.com/api/?type=meat-and-filler¶s=5&format=text", pass, fail )
end
function draw()
print(t)
end
@skar You can also see that the callback inside the tween is running on the ‘main’ coroutine too:
function setup()
-- Works
print("Downloading on main thread", coroutine.running())
http.request("https://baconipsum.com/api/?type=meat-and-filler¶s=5&format=text", function(data)
print("Main thread request done.", coroutine.running())
end)
-- Does not work
local co = coroutine.create(function()
print("Downloading on coroutine thread", coroutine.running())
tween(0.01, {}, {}, nil, function()
http.request("https://baconipsum.com/api/?type=meat-and-filler¶s=5&format=text", function(data)
print("Coroutine request done.", coroutine.running())
end)
end).time = 0.0
end)
coroutine.resume(co)
end
function draw()
print()
end