run_proc: no thread in background mode and call done in main thread

This commit is contained in:
Moritz Brückner 2021-06-24 14:59:32 +02:00
parent 66856e7ecc
commit d18aede964
2 changed files with 55 additions and 5 deletions

View file

@ -1,5 +1,6 @@
import importlib
import os
import queue
import sys
import bpy
@ -102,6 +103,24 @@ def always():
space.node_tree.arm_cached = False
return 0.5
def poll_threads() -> float:
"""Polls the thread callback queue and if a thread has finished, it
is joined with the main thread and the corresponding callback is
executed in the main thread.
"""
try:
thread, callback = make.thread_callback_queue.get(block=False)
except queue.Empty:
return 0.25
thread.join()
callback()
# Quickly check if another thread has finished
return 0.01
appended_py_paths = []
context_screen = None
@ -181,7 +200,9 @@ def register():
bpy.app.handlers.load_post.append(on_load_post)
bpy.app.handlers.depsgraph_update_post.append(on_depsgraph_update_post)
# bpy.app.handlers.undo_post.append(on_undo_post)
bpy.app.timers.register(always, persistent=True)
bpy.app.timers.register(poll_threads, persistent=True)
if arm.utils.get_fp() != '':
appended_py_paths = []

View file

@ -10,6 +10,8 @@ import webbrowser
import shlex
import errno
import math
from typing import Callable
from queue import Queue
import bpy
@ -28,15 +30,42 @@ import arm.write_data as write_data
scripts_mtime = 0 # Monitor source changes
profile_time = 0
def run_proc(cmd, done):
def fn(p, done):
p.wait()
if done != None:
# Queue of threads and their done callbacks. Item format: [thread, done]
thread_callback_queue = Queue(maxsize=0)
def run_proc(cmd, done: Callable) -> subprocess.Popen:
"""Creates a subprocess with the given command and returns it.
If Blender is not running in background mode, a thread is spawned
that waits until the subprocess has finished executing to not freeze
the UI, otherwise (in background mode) execution is blocked until
the subprocess has finished.
If `done` is not `None`, it is called afterwards in the main thread.
"""
use_thread = not bpy.app.background
def wait_for_proc(proc: subprocess.Popen):
proc.wait()
if use_thread:
# Put the done callback into the callback queue so that it
# can be received by a polling function in the main thread
thread_callback_queue.put([threading.current_thread(), done], block=True)
else:
done()
p = subprocess.Popen(cmd)
threading.Thread(target=fn, args=(p, done)).start()
if use_thread:
threading.Thread(target=wait_for_proc, args=(p,)).start()
else:
wait_for_proc(p)
return p
def compile_shader_pass(res, raw_shaders_path, shader_name, defs, make_variants):
os.chdir(raw_shaders_path + '/' + shader_name)