Also using asyncio for the display thread.
When I tried this before threading was working better. Now asyncio is doing better. Recently, exceptions were happening occasionaly in the update thread. I guess due to races. They should go away now. From now on, if a coroutine takes too long the interface will hitch. Should investigate if sync_to_filesystem is taking too long and if it can yield. There are no uses of threading now.
This commit is contained in:
parent
c99dd27dc6
commit
62fa8269dc
2 changed files with 19 additions and 36 deletions
39
fill3.py
39
fill3.py
|
|
@ -4,13 +4,13 @@
|
||||||
# Copyright (C) 2015-2016 Andrew Hamilton. All rights reserved.
|
# Copyright (C) 2015-2016 Andrew Hamilton. All rights reserved.
|
||||||
# Licensed under the Artistic License 2.0.
|
# Licensed under the Artistic License 2.0.
|
||||||
|
|
||||||
|
import asyncio
|
||||||
import collections
|
import collections
|
||||||
import contextlib
|
import contextlib
|
||||||
import itertools
|
import itertools
|
||||||
import os
|
import os
|
||||||
import signal
|
import signal
|
||||||
import sys
|
import sys
|
||||||
import threading
|
|
||||||
|
|
||||||
import urwid
|
import urwid
|
||||||
import urwid.raw_display
|
import urwid.raw_display
|
||||||
|
|
@ -401,6 +401,9 @@ class Placeholder:
|
||||||
return self.widget.appearance(dimensions)
|
return self.widget.appearance(dimensions)
|
||||||
|
|
||||||
|
|
||||||
|
##########################
|
||||||
|
|
||||||
|
|
||||||
def draw_screen(widget):
|
def draw_screen(widget):
|
||||||
appearance = widget.appearance(os.get_terminal_size())
|
appearance = widget.appearance(os.get_terminal_size())
|
||||||
print(terminal.move(0, 0), *appearance, sep="", end="", flush=True)
|
print(terminal.move(0, 0), *appearance, sep="", end="", flush=True)
|
||||||
|
|
@ -433,43 +436,27 @@ def _urwid_screen():
|
||||||
screen.stop()
|
screen.stop()
|
||||||
|
|
||||||
|
|
||||||
_UPDATE_THREAD_STOPPED = threading.Event()
|
async def _update_screen(screen_widget, appearance_changed_event):
|
||||||
|
|
||||||
|
|
||||||
def _update_screen(main_widget, appearance_changed_event):
|
|
||||||
while True:
|
while True:
|
||||||
appearance_changed_event.wait()
|
await appearance_changed_event.wait()
|
||||||
appearance_changed_event.clear()
|
appearance_changed_event.clear()
|
||||||
if _UPDATE_THREAD_STOPPED.is_set():
|
patch_screen(screen_widget)
|
||||||
break
|
|
||||||
patch_screen(main_widget)
|
|
||||||
|
|
||||||
|
|
||||||
def main(loop, appearance_changed_event, screen, exit_loop=None):
|
def main(loop, appearance_changed_event, screen_widget, exit_loop=None):
|
||||||
appearance_changed_event.set()
|
appearance_changed_event.set()
|
||||||
update_display_thread = threading.Thread(
|
|
||||||
target=_update_screen, args=(screen, appearance_changed_event),
|
|
||||||
daemon=True)
|
|
||||||
|
|
||||||
def exit_loop_():
|
|
||||||
loop.stop()
|
|
||||||
if exit_loop is None:
|
if exit_loop is None:
|
||||||
exit_loop = exit_loop_
|
exit_loop = loop.stop
|
||||||
loop.add_signal_handler(signal.SIGWINCH, appearance_changed_event.set)
|
loop.add_signal_handler(signal.SIGWINCH, appearance_changed_event.set)
|
||||||
loop.add_signal_handler(signal.SIGINT, exit_loop)
|
loop.add_signal_handler(signal.SIGINT, exit_loop)
|
||||||
loop.add_signal_handler(signal.SIGTERM, exit_loop)
|
loop.add_signal_handler(signal.SIGTERM, exit_loop)
|
||||||
|
asyncio.ensure_future(_update_screen(screen_widget,
|
||||||
|
appearance_changed_event))
|
||||||
with terminal.hidden_cursor():
|
with terminal.hidden_cursor():
|
||||||
with _urwid_screen() as urwid_screen:
|
with _urwid_screen() as urwid_screen:
|
||||||
|
|
||||||
def on_input(urwid_screen):
|
def on_input(urwid_screen):
|
||||||
for event in urwid_screen.get_input():
|
for event in urwid_screen.get_input():
|
||||||
screen.on_input_event(event)
|
screen_widget.on_input_event(event)
|
||||||
loop.add_reader(sys.stdin, on_input, urwid_screen)
|
loop.add_reader(sys.stdin, on_input, urwid_screen)
|
||||||
update_display_thread.start()
|
loop.run_forever()
|
||||||
try:
|
|
||||||
loop.run_forever()
|
|
||||||
finally:
|
|
||||||
_UPDATE_THREAD_STOPPED.set()
|
|
||||||
appearance_changed_event.set()
|
|
||||||
update_display_thread.join()
|
|
||||||
# loop.close()
|
|
||||||
|
|
|
||||||
16
vigil
16
vigil
|
|
@ -33,7 +33,6 @@ import signal
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import threading
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import docopt
|
import docopt
|
||||||
|
|
@ -198,7 +197,6 @@ class Summary:
|
||||||
self._view_widget = fill3.View.from_widget(self)
|
self._view_widget = fill3.View.from_widget(self)
|
||||||
self.__cursor_position = (0, 0)
|
self.__cursor_position = (0, 0)
|
||||||
self.closest_placeholder_generator = None
|
self.closest_placeholder_generator = None
|
||||||
self._lock = threading.Lock()
|
|
||||||
self._cache = {}
|
self._cache = {}
|
||||||
self.is_directory_sort = True
|
self.is_directory_sort = True
|
||||||
self._max_width = None
|
self._max_width = None
|
||||||
|
|
@ -296,12 +294,11 @@ class Summary:
|
||||||
yield result
|
yield result
|
||||||
|
|
||||||
def get_closest_placeholder(self):
|
def get_closest_placeholder(self):
|
||||||
with self._lock:
|
try:
|
||||||
try:
|
return self.closest_placeholder_generator.send(None)
|
||||||
return self.closest_placeholder_generator.send(None)
|
except AttributeError:
|
||||||
except AttributeError:
|
self.closest_placeholder_generator = self._placeholder_spiral()
|
||||||
self.closest_placeholder_generator = self._placeholder_spiral()
|
return self.closest_placeholder_generator.send(None)
|
||||||
return self.closest_placeholder_generator.send(None)
|
|
||||||
|
|
||||||
def appearance_dimensions(self):
|
def appearance_dimensions(self):
|
||||||
return self._max_path_length + 1 + self._max_width, len(self._column)
|
return self._max_path_length + 1 + self._max_width, len(self._column)
|
||||||
|
|
@ -919,7 +916,6 @@ def load_state(pickle_path, jobs_added_event, appearance_changed_event,
|
||||||
screen._appearance_changed_event = appearance_changed_event
|
screen._appearance_changed_event = appearance_changed_event
|
||||||
screen._main_loop = loop
|
screen._main_loop = loop
|
||||||
summary = screen._summary
|
summary = screen._summary
|
||||||
summary._lock = threading.Lock()
|
|
||||||
summary._jobs_added_event = jobs_added_event
|
summary._jobs_added_event = jobs_added_event
|
||||||
summary._root_path = root_path
|
summary._root_path = root_path
|
||||||
log = screen._log
|
log = screen._log
|
||||||
|
|
@ -943,7 +939,7 @@ def main(root_path, loop, worker_count=None, is_sandboxed=True,
|
||||||
worker_count = multiprocessing.cpu_count() * 2
|
worker_count = multiprocessing.cpu_count() * 2
|
||||||
pickle_path = os.path.join(tools.CACHE_PATH, "summary.pickle")
|
pickle_path = os.path.join(tools.CACHE_PATH, "summary.pickle")
|
||||||
jobs_added_event = asyncio.Event()
|
jobs_added_event = asyncio.Event()
|
||||||
appearance_changed_event = threading.Event()
|
appearance_changed_event = asyncio.Event()
|
||||||
summary, screen, log, is_first_run = load_state(
|
summary, screen, log, is_first_run = load_state(
|
||||||
pickle_path, jobs_added_event, appearance_changed_event, root_path,
|
pickle_path, jobs_added_event, appearance_changed_event, root_path,
|
||||||
loop)
|
loop)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue