diff options
| author | ruki <[email protected]> | 2025-11-21 00:53:26 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2025-11-21 11:28:51 +0800 |
| commit | 00782576966755c6bcebd30252e51333a6603d25 (patch) | |
| tree | 919514f918bd790c32044a623aec43893198cb55 | |
| parent | 66dec67272856110859d38c01043fd2564f9c7a7 (diff) | |
improve runjobs
| -rw-r--r-- | xmake/modules/async/runjobs.lua | 169 |
1 files changed, 105 insertions, 64 deletions
diff --git a/xmake/modules/async/runjobs.lua b/xmake/modules/async/runjobs.lua index 109ccd3f3..751260da5 100644 --- a/xmake/modules/async/runjobs.lua +++ b/xmake/modules/async/runjobs.lua @@ -33,10 +33,10 @@ function _print_backchars(backnum) end end --- init progress -function _init_progress(state, opt) +-- init waiting indicator +function _init_waiting_indicator(state, opt) opt = opt or {} - + -- init waiting indicator helper -- we need to hide wait characters if is not a tty local waiting_indicator_opt = opt.waiting_indicator @@ -49,6 +49,11 @@ function _init_progress(state, opt) end state.waiting_indicator_helper = waiting_indicator.new(nil, indicator_opt) end +end + +-- init progress +function _init_progress(state, opt) + opt = opt or {} -- init progress wrapper state.progress_finished_count = 0 @@ -79,6 +84,82 @@ function _init_progress(state, opt) state.progress_refresh_timeout = 500 end +-- start timer (on_timer callback) +function _start_timer(state, name, opt) + if opt.on_timer then + state.on_timer = opt.on_timer + state.group_timer = state.group_name .. "/timer" + scheduler.co_group_begin(state.group_timer, function (co_group) + scheduler.co_start_withopt({name = name .. "/timer", isolate = opt.isolate}, _timer_loop, state) + end) + end +end + +-- start waiting indicator timer +function _start_waiting_indicator_timer(state, name, opt) + if state.show_waiting_indicator then + state.group_waiting_indicator_timer = state.group_name .. "/waiting_indicator" + scheduler.co_group_begin(state.group_waiting_indicator_timer, function (co_group) + scheduler.co_start_withopt({name = name .. "/waiting_indicator", isolate = opt.isolate}, _waiting_indicator_loop, state) + end) + end +end + +-- start progress refresh timer for multirow progress +function _start_progress_refresh_timer(state, name, opt) + if opt.progress_refresh and progress.is_multirow() then + state.group_progress_refresh_timer = state.group_name .. "/progress_refresh" + state.all_tasks_started = false + -- create semaphore for refresh loop + state.progress_refresh_semaphore = scheduler.co_semaphore(state.group_name .. "/progress_refresh", 0) + -- start progress refresh loop + scheduler.co_group_begin(state.group_progress_refresh_timer, function (co_group) + scheduler.co_start_withopt({name = name .. "/progress_refresh", isolate = opt.isolate}, _progress_refresh_loop, state) + end) + end +end + +-- start all timers +function _start_timers(state, name, opt) + _start_timer(state, name, opt) + _start_waiting_indicator_timer(state, name, opt) + _start_progress_refresh_timer(state, name, opt) +end + +-- stop all timers and notify them to exit +function _stop_timers(state) + -- signal progress refresh loop to exit quickly + if state.group_progress_refresh_timer and state.progress_refresh_semaphore then + state.progress_refresh_semaphore:post(1) + end +end + +-- wait all timer jobs exited +function _wait_timers(state) + if state.group_timer then + scheduler.co_group_wait(state.group_timer) + end + if state.group_waiting_indicator_timer then + scheduler.co_group_wait(state.group_waiting_indicator_timer) + end + if state.group_progress_refresh_timer then + scheduler.co_group_wait(state.group_progress_refresh_timer) + end +end + +-- exit waiting indicator +function _exit_waiting_indicator(state) + if state.show_waiting_indicator then + _print_backchars(state.backnum) + state.waiting_indicator_helper:stop() + end +end + +-- exit progress +function _exit_progress(state) + progress.show_abort() +end + -- the timer loop function _timer_loop(state) local timeout = state.timeout @@ -257,12 +338,9 @@ function _consume_jobs_loop(state, run_in_remote) -- stop timer and disable show waitchars first state.stop = true - -- stop progress - progress.show_abort() - if state.show_waiting_indicator then - _print_backchars(state.backnum) - state.waiting_indicator_helper:stop() - end + -- stop progress and waiting indicator + _exit_progress(state) + _exit_waiting_indicator(state) -- we need re-throw this errors outside scheduler state.abort = true @@ -343,7 +421,10 @@ function main(name, jobs, opt) assert(jobs, "runjobs: no jobs!") state.jobs = jobs - -- show waiting tips? + -- init waiting indicator + _init_waiting_indicator(state, opt) + + -- init progress _init_progress(state, opt) -- isolate environments @@ -354,30 +435,12 @@ function main(name, jobs, opt) co_running:isolate(true) end - -- run timer + -- init timer state state.stop = false state.running_jobs_indices = {} - state.all_tasks_started = false - local group_timer - if opt.on_timer then - state.on_timer = opt.on_timer - group_timer = state.group_name .. "/timer" - scheduler.co_group_begin(group_timer, function (co_group) - scheduler.co_start_withopt({name = name .. "/timer", isolate = opt.isolate}, _timer_loop, state) - end) - elseif state.show_waiting_indicator then - group_timer = state.group_name .. "/timer" - scheduler.co_group_begin(group_timer, function (co_group) - scheduler.co_start_withopt({name = name .. "/tips", isolate = opt.isolate}, _waiting_indicator_loop, state) - end) - end - -- start independent refresh timer for multirow progress - local group_progress_refresh_timer = nil - local need_progress_refresh_timer = opt.progress_refresh and progress.is_multirow() - if need_progress_refresh_timer then - group_progress_refresh_timer = state.group_name .. "/progress_refresh" - end + -- start all timers + _start_timers(state, name, opt) -- run jobs local distcc = opt.distcc @@ -392,11 +455,6 @@ function main(name, jobs, opt) if distcc then state.distcc_semaphore = scheduler.co_semaphore(state.group_name .. "/distcc", 0) end - -- create semaphore for refresh loop - if need_progress_refresh_timer then - -- semaphore to wait for all tasks started and for refresh timer to signal refresh loop - state.progress_refresh_semaphore = scheduler.co_semaphore(state.group_name .. "/progress_refresh", 0) - end -- @note we can set `remote_only = true` to run all jobs in remote only local local_comax = 0 if not opt.remote_only then @@ -414,43 +472,26 @@ function main(name, jobs, opt) end end) - -- start refresh loop after semaphore is created - if need_progress_refresh_timer then - scheduler.co_group_begin(group_progress_refresh_timer, function (co_group) - scheduler.co_start_withopt({name = name .. "/progress_refresh", isolate = opt.isolate}, _progress_refresh_loop, state) - end) - end - -- wait all jobs exited scheduler.co_group_wait(state.group_name) - -- wait timer job exited - if group_timer then - state.stop = true - scheduler.co_group_wait(group_timer) - end - - -- wait refresh timer job exited and signal it to exit quickly - if group_progress_refresh_timer then - state.stop = true - -- post signal to refresh loop to wake it up for quick exit - if state.progress_refresh_semaphore then - state.progress_refresh_semaphore:post(1) - end - scheduler.co_group_wait(group_progress_refresh_timer) - end + -- stop all timers and notify them to exit + state.stop = true + _stop_timers(state) + + -- wait all timer jobs exited + _wait_timers(state) -- restore isolated environments if co_running and opt.isolate then co_running:isolate(is_isolated) end - -- stop progress - progress.show_abort() - if state.show_waiting_indicator then - _print_backchars(state.backnum) - state.waiting_indicator_helper:stop() - end + -- exit progress + _exit_progress(state) + + -- exit waiting indicator + _exit_waiting_indicator(state) -- do exit callback if opt.on_exit then |
