Made coroutines make more sense, and fixed a bug. (#1381)

* Made coroutines make more sense, and fixed a bug.

* Fixed typo.

* Additional checking for off-cycles.

* Fixed issue with calling step too much.

* If we have no redraw, set next step time for next frame.

* Added in `now` variables to reduce calls.
This commit is contained in:
Adam 2023-03-28 12:57:47 -04:00 committed by George Sokianos
parent d0ec3aa0fe
commit b348acaa81
1 changed files with 35 additions and 23 deletions

View File

@ -305,7 +305,7 @@ function core.add_project_directory(path)
end end
end end
if project_dir_open then if project_dir_open then
coroutine.yield(changed and 0.05 or 0) coroutine.yield(changed and 0 or 0.05)
else else
return return
end end
@ -1384,7 +1384,7 @@ end
local run_threads = coroutine.wrap(function() local run_threads = coroutine.wrap(function()
while true do while true do
local max_time = 1 / config.fps - 0.004 local max_time = 1 / config.fps - 0.004
local need_more_work = false local minimal_time_to_wake = math.huge
for k, thread in pairs(core.threads) do for k, thread in pairs(core.threads) do
-- run thread -- run thread
@ -1398,48 +1398,60 @@ local run_threads = coroutine.wrap(function()
end end
elseif wait then elseif wait then
thread.wake = system.get_time() + wait thread.wake = system.get_time() + wait
minimal_time_to_wake = math.min(minimal_time_to_wake, wait)
else else
need_more_work = true minimal_time_to_wake = 0
end end
else
minimal_time_to_wake = math.min(minimal_time_to_wake, thread.wake - system.get_time())
end end
-- stop running threads if we're about to hit the end of frame -- stop running threads if we're about to hit the end of frame
if system.get_time() - core.frame_start > max_time then if system.get_time() - core.frame_start > max_time then
coroutine.yield(true) coroutine.yield(0)
end end
end end
if not need_more_work then coroutine.yield(false) end coroutine.yield(minimal_time_to_wake)
end end
end) end)
function core.run() function core.run()
local idle_iterations = 0 local next_step
while true do while true do
core.frame_start = system.get_time() core.frame_start = system.get_time()
local need_more_work = run_threads() local time_to_wake = run_threads()
local did_redraw = core.step() local did_redraw = false
if not next_step or system.get_time() >= next_step then
did_redraw = core.step()
next_step = nil
end
if core.restart_request or core.quit_request then break end if core.restart_request or core.quit_request then break end
if not did_redraw and not need_more_work then
idle_iterations = idle_iterations + 1 if not did_redraw then
-- do not wait of events at idle_iterations = 1 to give a chance at core.step to run if system.window_has_focus() then
-- and set "redraw" flag. local now = system.get_time()
if idle_iterations > 1 then if not next_step then -- compute the time until the next blink
if system.window_has_focus() then local t = now - core.blink_start
-- keep running even with no events to make the cursor blinks
local t = system.get_time() - core.blink_start
local h = config.blink_period / 2 local h = config.blink_period / 2
local dt = math.ceil(t / h) * h - t local dt = math.ceil(t / h) * h - t
system.wait_event(dt + 1 / config.fps) local cursor_time_to_wake = dt + 1 / config.fps
else next_step = now + cursor_time_to_wake
system.wait_event()
end end
if time_to_wake > 0 and system.wait_event(math.min(next_step - now, time_to_wake)) then
next_step = nil -- if we've recevied an event, perform a step
end
else
system.wait_event()
next_step = nil -- perform a step when we're not in focus if get we an event
end end
else else -- if we redrew, then make sure we only draw at most FPS/sec
idle_iterations = 0 local now = system.get_time()
local elapsed = system.get_time() - core.frame_start local elapsed = now - core.frame_start
system.sleep(math.max(0, 1 / config.fps - elapsed)) local next_frame = math.max(0, 1 / config.fps - elapsed)
next_step = next_step or (now + next_frame)
system.sleep(math.min(next_frame, time_to_wake))
end end
end end
end end