Merge remote-tracking branch 'zyx-i/no-update_lock' into develop

This commit is contained in:
Kim Silkebækken 2013-03-25 13:49:50 +01:00
commit 40436c549a
3 changed files with 40 additions and 33 deletions

View File

@ -1,9 +1,18 @@
# vim:fileencoding=utf-8:noet # vim:fileencoding=utf-8:noet
import zsh import zsh
import atexit
from powerline.shell import ShellPowerline from powerline.shell import ShellPowerline
from powerline.lib import parsedotval from powerline.lib import parsedotval
used_powerlines = []
def shutdown():
for powerline in used_powerlines:
powerline.renderer.shutdown()
def get_var_config(var): def get_var_config(var):
try: try:
return [parsedotval(i) for i in zsh.getvalue(var).items()] return [parsedotval(i) for i in zsh.getvalue(var).items()]
@ -69,17 +78,17 @@ class Environment(object):
class Prompt(object): class Prompt(object):
__slots__ = ('render', 'side', 'savedpsvar', 'savedps', 'args') __slots__ = ('powerline', 'side', 'savedpsvar', 'savedps', 'args')
def __init__(self, powerline, side, savedpsvar=None, savedps=None): def __init__(self, powerline, side, savedpsvar=None, savedps=None):
self.render = powerline.renderer.render self.powerline = powerline
self.side = side self.side = side
self.savedpsvar = savedpsvar self.savedpsvar = savedpsvar
self.savedps = savedps self.savedps = savedps
self.args = powerline.args self.args = powerline.args
def __str__(self): def __str__(self):
r = self.render(width=zsh.columns(), side=self.side, segment_info=self.args) r = self.powerline.renderer.render(width=zsh.columns(), side=self.side, segment_info=self.args)
if type(r) is not str: if type(r) is not str:
if type(r) is bytes: if type(r) is bytes:
return r.decode('utf-8') return r.decode('utf-8')
@ -90,6 +99,9 @@ class Prompt(object):
def __del__(self): def __del__(self):
if self.savedps: if self.savedps:
zsh.setvalue(self.savedpsvar, self.savedps) zsh.setvalue(self.savedpsvar, self.savedps)
used_powerlines.remove(self.powerline)
if self.powerline not in used_powerlines:
self.powerline.renderer.shutdown()
def set_prompt(powerline, psvar, side): def set_prompt(powerline, psvar, side):
@ -103,5 +115,8 @@ def set_prompt(powerline, psvar, side):
def setup(): def setup():
environ = Environment() environ = Environment()
powerline = ShellPowerline(Args(), environ=environ, getcwd=lambda: environ['PWD']) powerline = ShellPowerline(Args(), environ=environ, getcwd=lambda: environ['PWD'])
used_powerlines.append(powerline)
used_powerlines.append(powerline)
set_prompt(powerline, 'PS1', 'left') set_prompt(powerline, 'PS1', 'left')
set_prompt(powerline, 'RPS1', 'right') set_prompt(powerline, 'RPS1', 'right')
atexit.register(shutdown)

View File

@ -4,21 +4,18 @@ from __future__ import absolute_import
from powerline.lib.time import monotonic from powerline.lib.time import monotonic
from time import sleep from threading import Thread, Lock, Event
from threading import Thread, Lock
class ThreadedSegment(object): class ThreadedSegment(object):
daemon = True
min_sleep_time = 0.1 min_sleep_time = 0.1
update_first = True update_first = True
interval = 1 interval = 1
def __init__(self): def __init__(self):
super(ThreadedSegment, self).__init__() super(ThreadedSegment, self).__init__()
self.update_lock = Lock() self.shutdown_event = Event()
self.write_lock = Lock() self.write_lock = Lock()
self.keep_going = True
self.run_once = True self.run_once = True
self.did_set_interval = False self.did_set_interval = False
self.thread = None self.thread = None
@ -39,6 +36,8 @@ class ThreadedSegment(object):
if update_first and self.update_first: if update_first and self.update_first:
self.update() self.update()
self.start() self.start()
elif not self.updated:
self.update()
if self.skip: if self.skip:
return self.crashed_value return self.crashed_value
@ -49,40 +48,29 @@ class ThreadedSegment(object):
return self.thread and self.thread.is_alive() return self.thread and self.thread.is_alive()
def start(self): def start(self):
self.keep_going = True
self.thread = Thread(target=self.run) self.thread = Thread(target=self.run)
self.thread.daemon = self.daemon
self.thread.start() self.thread.start()
def sleep(self, adjust_time): def sleep(self, adjust_time):
sleep(max(self.interval - adjust_time, self.min_sleep_time)) self.shutdown_event.wait(max(self.interval - adjust_time, self.min_sleep_time))
if self.shutdown_event.is_set():
self.keep_going = False
def run(self): def run(self):
while self.keep_going: while self.keep_going:
start_time = monotonic() start_time = monotonic()
try: try:
if self.update_lock.acquire(False): self.update()
try: except Exception as e:
self.update() self.error('Exception while updating: {0}', str(e))
except Exception as e: self.skip = True
self.error('Exception while updating: {0}', str(e)) else:
self.skip = True self.skip = False
else:
self.skip = False
else:
return
finally:
# Release lock in any case. If it is not locked in this thread,
# it was done in main thread in .shutdown method, and the lock
# will never be released.
self.update_lock.release()
self.sleep(monotonic() - start_time) self.sleep(monotonic() - start_time)
def shutdown(self): def shutdown(self):
if self.keep_going: self.shutdown_event.set()
self.keep_going = False
self.update_lock.acquire()
def set_interval(self, interval=None): def set_interval(self, interval=None):
# Allowing “interval” keyword in configuration. # Allowing “interval” keyword in configuration.
@ -93,9 +81,10 @@ class ThreadedSegment(object):
self.interval = interval self.interval = interval
self.has_set_interval = True self.has_set_interval = True
def set_state(self, interval=None, **kwargs): def set_state(self, interval=None, update_first=True, **kwargs):
if not self.did_set_interval or interval: if not self.did_set_interval or interval:
self.set_interval(interval) self.set_interval(interval)
self.updated = not (update_first and self.update_first)
def startup(self, pl, **kwargs): def startup(self, pl, **kwargs):
self.run_once = False self.run_once = False
@ -124,12 +113,13 @@ def printed(func):
class KwThreadedSegment(ThreadedSegment): class KwThreadedSegment(ThreadedSegment):
drop_interval = 10 * 60 drop_interval = 10 * 60
update_first = False update_first = True
def __init__(self): def __init__(self):
super(KwThreadedSegment, self).__init__() super(KwThreadedSegment, self).__init__()
self.queries = {} self.queries = {}
self.crashed = set() self.crashed = set()
self.updated = True
@staticmethod @staticmethod
def key(**kwargs): def key(**kwargs):
@ -170,7 +160,7 @@ class KwThreadedSegment(ThreadedSegment):
for key in removes: for key in removes:
self.queries.pop(key) self.queries.pop(key)
def set_state(self, interval=None, **kwargs): def set_state(self, interval=None, update_first=True, **kwargs):
if not self.did_set_interval or (interval < self.interval): if not self.did_set_interval or (interval < self.interval):
self.set_interval(interval) self.set_interval(interval)

View File

@ -193,6 +193,7 @@ class TestCommon(TestCase):
def test_network_load(self): def test_network_load(self):
from time import sleep from time import sleep
def gb(interface): def gb(interface):
return None return None
@ -251,6 +252,7 @@ class TestCommon(TestCase):
{'divider_highlight_group': 'background:divider', 'contents': 'r 1 KiB/s', 'highlight_group': ['network_load_recv', 'network_load']}, {'divider_highlight_group': 'background:divider', 'contents': 'r 1 KiB/s', 'highlight_group': ['network_load_recv', 'network_load']},
{'divider_highlight_group': 'background:divider', 'contents': 's 2 KiB/s', 'highlight_group': ['network_load_sent_gradient', 'network_load_gradient', 'network_load_sent', 'network_load'], 'gradient_level': ApproxEqual()}, {'divider_highlight_group': 'background:divider', 'contents': 's 2 KiB/s', 'highlight_group': ['network_load_sent_gradient', 'network_load_gradient', 'network_load_sent', 'network_load'], 'gradient_level': ApproxEqual()},
]) ])
common.network_load.shutdown()
def test_virtualenv(self): def test_virtualenv(self):
with replace_env('VIRTUAL_ENV', '/abc/def/ghi') as pl: with replace_env('VIRTUAL_ENV', '/abc/def/ghi') as pl: