kopia lustrzana https://github.com/inkstitch/inkstitch
get rid of thread killing
Switching to a cooperative model. This has the downside that a long patch computation will cause the simulate window to take longer to update, but in practice the longest this will be is a couple of seconds (for a very complicated autofill region).pull/10/head
rodzic
7152caa14d
commit
cb6df39773
|
@ -6,7 +6,7 @@ import sys
|
||||||
import json
|
import json
|
||||||
import traceback
|
import traceback
|
||||||
import time
|
import time
|
||||||
from threading import Thread
|
from threading import Thread, Event
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
import wx
|
import wx
|
||||||
|
@ -18,40 +18,6 @@ from functools import partial
|
||||||
from itertools import groupby
|
from itertools import groupby
|
||||||
from embroider_simulate import EmbroiderySimulator
|
from embroider_simulate import EmbroiderySimulator
|
||||||
|
|
||||||
class KillableThread(Thread):
|
|
||||||
"""A subclass of threading.Thread, with a kill() method."""
|
|
||||||
def __init__(self, *args, **keywords):
|
|
||||||
Thread.__init__(self, *args, **keywords)
|
|
||||||
self.killed = False
|
|
||||||
|
|
||||||
def start(self):
|
|
||||||
"""Start the thread."""
|
|
||||||
self.__run_backup = self.run
|
|
||||||
self.run = self.__run # Force the Thread to install our trace.
|
|
||||||
Thread.start(self)
|
|
||||||
|
|
||||||
def __run(self):
|
|
||||||
"""Hacked run function, which installs the trace."""
|
|
||||||
sys.settrace(self.globaltrace)
|
|
||||||
self.__run_backup()
|
|
||||||
self.run = self.__run_backup
|
|
||||||
|
|
||||||
def globaltrace(self, frame, why, arg):
|
|
||||||
if why == 'call':
|
|
||||||
return self.localtrace
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def localtrace(self, frame, why, arg):
|
|
||||||
if self.killed:
|
|
||||||
if why == 'line':
|
|
||||||
raise SystemExit()
|
|
||||||
return self.localtrace
|
|
||||||
|
|
||||||
def kill(self):
|
|
||||||
self.killed = True
|
|
||||||
|
|
||||||
|
|
||||||
def presets_path():
|
def presets_path():
|
||||||
try:
|
try:
|
||||||
import appdirs
|
import appdirs
|
||||||
|
@ -365,7 +331,7 @@ class SettingsFrame(wx.Frame):
|
||||||
|
|
||||||
self.simulate_window = None
|
self.simulate_window = None
|
||||||
self.simulate_thread = None
|
self.simulate_thread = None
|
||||||
self.thread_num = 0
|
self.simulate_refresh_needed = Event()
|
||||||
|
|
||||||
self.presets_box = wx.StaticBox(self, wx.ID_ANY, label="Presets")
|
self.presets_box = wx.StaticBox(self, wx.ID_ANY, label="Presets")
|
||||||
|
|
||||||
|
@ -402,12 +368,18 @@ class SettingsFrame(wx.Frame):
|
||||||
self.simulate_window.stop()
|
self.simulate_window.stop()
|
||||||
self.simulate_window.clear()
|
self.simulate_window.clear()
|
||||||
|
|
||||||
if self.simulate_thread and self.simulate_thread.is_alive():
|
if not self.simulate_thread or not self.simulate_thread.is_alive():
|
||||||
self.simulate_thread.kill()
|
self.simulate_thread = Thread(target=self.simulate_worker)
|
||||||
|
self.simulate_thread.daemon = True
|
||||||
|
self.simulate_thread.start()
|
||||||
|
|
||||||
self.simulate_thread = KillableThread(target=self.update_patches, name="Simulate%d" % self.thread_num)
|
self.simulate_refresh_needed.set()
|
||||||
self.simulate_thread.start()
|
|
||||||
self.thread_num += 1
|
def simulate_worker(self):
|
||||||
|
while True:
|
||||||
|
self.simulate_refresh_needed.wait()
|
||||||
|
self.simulate_refresh_needed.clear()
|
||||||
|
self.update_patches()
|
||||||
|
|
||||||
def update_patches(self):
|
def update_patches(self):
|
||||||
patches = self.generate_patches()
|
patches = self.generate_patches()
|
||||||
|
@ -448,6 +420,10 @@ class SettingsFrame(wx.Frame):
|
||||||
try:
|
try:
|
||||||
if tab.enabled() and not tab.is_dependent_tab():
|
if tab.enabled() and not tab.is_dependent_tab():
|
||||||
for node in tab.nodes:
|
for node in tab.nodes:
|
||||||
|
if self.simulate_refresh_needed.is_set():
|
||||||
|
# cancel, we need to start over
|
||||||
|
return []
|
||||||
|
|
||||||
# Making a copy of the embroidery element is an easy
|
# Making a copy of the embroidery element is an easy
|
||||||
# way to drop the cache in the @cache decorators used
|
# way to drop the cache in the @cache decorators used
|
||||||
# for many params in embroider.py.
|
# for many params in embroider.py.
|
||||||
|
|
Ładowanie…
Reference in New Issue