mirror of
https://github.com/powerline/powerline.git
synced 2025-04-08 19:25:04 +02:00
Remove ThreadedSegment.write_lock
Assuming getattr(self, 'update_value') and setattr(self, 'update_value', value) are atomic. True with cpython unless somebody defined __getattribute__ or __setattr__.
This commit is contained in:
parent
ff6fd64339
commit
29f29213a9
@ -84,7 +84,7 @@ endfunction
|
||||
augroup Powerline
|
||||
autocmd! ColorScheme * :exec s:powerline_pycmd 'powerline.renderer.reset_highlight()'
|
||||
autocmd! VimEnter * :redrawstatus!
|
||||
autocmd! VimLeave * :exec s:powerline_pycmd 'powerline.shutdown()'
|
||||
autocmd! VimLeavePre * :exec s:powerline_pycmd 'powerline.shutdown()'
|
||||
augroup END
|
||||
|
||||
exec s:powerline_pycmd 'powerline = VimPowerline()'
|
||||
|
@ -16,33 +16,39 @@ class ThreadedSegment(object):
|
||||
def __init__(self):
|
||||
super(ThreadedSegment, self).__init__()
|
||||
self.shutdown_event = Event()
|
||||
self.write_lock = Lock()
|
||||
self.run_once = True
|
||||
self.thread = None
|
||||
self.skip = False
|
||||
self.crashed_value = None
|
||||
self.update_value = None
|
||||
|
||||
def __call__(self, pl, update_first=True, **kwargs):
|
||||
if self.run_once:
|
||||
self.pl = pl
|
||||
self.set_state(**kwargs)
|
||||
self.update()
|
||||
update_value = self.get_update_value(True)
|
||||
elif not self.is_alive():
|
||||
# Without this we will not have to wait long until receiving bug “I
|
||||
# opened vim, but branch information is only shown after I move
|
||||
# cursor”.
|
||||
#
|
||||
# If running once .update() is called in __call__.
|
||||
if update_first and self.update_first:
|
||||
self.update()
|
||||
update_value = self.get_update_value(update_first and self.update_first)
|
||||
self.start()
|
||||
elif not self.updated:
|
||||
self.update()
|
||||
update_value = self.get_update_value(True)
|
||||
else:
|
||||
update_value = self.update_value
|
||||
|
||||
if self.skip:
|
||||
return self.crashed_value
|
||||
with self.write_lock:
|
||||
return self.render(update_first=update_first, pl=pl, **kwargs)
|
||||
|
||||
return self.render(update_value, update_first=update_first, pl=pl, **kwargs)
|
||||
|
||||
def get_update_value(self, update=False):
|
||||
if update:
|
||||
self.update_value = self.update(self.update_value)
|
||||
return self.update_value
|
||||
|
||||
def is_alive(self):
|
||||
return self.thread and self.thread.is_alive()
|
||||
@ -57,7 +63,7 @@ class ThreadedSegment(object):
|
||||
while not self.shutdown_event.is_set():
|
||||
start_time = monotonic()
|
||||
try:
|
||||
self.update()
|
||||
self.update(self.update_value)
|
||||
except Exception as e:
|
||||
self.error('Exception while updating: {0}', str(e))
|
||||
self.skip = True
|
||||
@ -115,48 +121,42 @@ class KwThreadedSegment(ThreadedSegment):
|
||||
|
||||
def __init__(self):
|
||||
super(KwThreadedSegment, self).__init__()
|
||||
self.queries = {}
|
||||
self.crashed = set()
|
||||
self.updated = True
|
||||
self.update_value = ({}, set())
|
||||
|
||||
@staticmethod
|
||||
def key(**kwargs):
|
||||
return frozenset(kwargs.items())
|
||||
|
||||
def render(self, update_first, **kwargs):
|
||||
def render(self, update_value, update_first, **kwargs):
|
||||
queries, crashed = update_value
|
||||
key = self.key(**kwargs)
|
||||
if key in self.crashed:
|
||||
if key in crashed:
|
||||
return self.crashed_value
|
||||
|
||||
try:
|
||||
update_state = self.queries[key][1]
|
||||
update_state = queries[key][1]
|
||||
except KeyError:
|
||||
# Allow only to forbid to compute missing values: in either user
|
||||
# configuration or in subclasses.
|
||||
update_state = self.compute_state(key) if update_first and self.update_first or self.run_once else None
|
||||
|
||||
# No locks: render method is already running with write_lock acquired.
|
||||
self.queries[key] = (monotonic(), update_state)
|
||||
queries[key] = (monotonic(), update_state)
|
||||
return self.render_one(update_state, **kwargs)
|
||||
|
||||
def update(self):
|
||||
def update(self, old_update_value):
|
||||
updates = {}
|
||||
removes = []
|
||||
for key, (last_query_time, state) in list(self.queries.items()):
|
||||
crashed = set()
|
||||
update_value = (updates, crashed)
|
||||
queries = old_update_value[0]
|
||||
for key, (last_query_time, state) in queries.items():
|
||||
if last_query_time < monotonic() < last_query_time + self.drop_interval:
|
||||
try:
|
||||
updates[key] = (last_query_time, self.compute_state(key))
|
||||
except Exception as e:
|
||||
self.exception('Exception while computing state for {0}: {1}', repr(key), str(e))
|
||||
with self.write_lock:
|
||||
self.crashed.add(key)
|
||||
else:
|
||||
removes.append(key)
|
||||
with self.write_lock:
|
||||
self.queries.update(updates)
|
||||
self.crashed -= set(updates)
|
||||
for key in removes:
|
||||
self.queries.pop(key)
|
||||
crashed.add(key)
|
||||
return update_value
|
||||
|
||||
def set_state(self, interval=None, update_first=True, **kwargs):
|
||||
self.set_interval(interval)
|
||||
@ -164,9 +164,6 @@ class KwThreadedSegment(ThreadedSegment):
|
||||
if self.update_first:
|
||||
self.update_first = update_first
|
||||
|
||||
with self.write_lock:
|
||||
self.queries.clear()
|
||||
|
||||
@staticmethod
|
||||
def render_one(update_state, **kwargs):
|
||||
return update_state
|
||||
|
@ -39,13 +39,13 @@ class RepositorySegment(KwThreadedSegment):
|
||||
def key(pl, **kwargs):
|
||||
return os.path.abspath(pl.getcwd())
|
||||
|
||||
def update(self):
|
||||
def update(self, *args):
|
||||
# .compute_state() is running only in this method, and only in one
|
||||
# thread, thus operations with .directories do not need write locks
|
||||
# (.render() method is not using .directories). If this is changed
|
||||
# .directories needs redesigning
|
||||
self.directories.clear()
|
||||
super(RepositorySegment, self).update()
|
||||
return super(RepositorySegment, self).update(*args)
|
||||
|
||||
def compute_state(self, path):
|
||||
repo = guess(path=path)
|
||||
@ -231,19 +231,19 @@ def _external_ip(query_url='http://ipv4.icanhazip.com/'):
|
||||
|
||||
|
||||
class ExternalIpSegment(ThreadedSegment):
|
||||
interval = 10
|
||||
|
||||
def set_state(self, query_url='http://ipv4.icanhazip.com/', **kwargs):
|
||||
self.query_url = query_url
|
||||
super(ExternalIpSegment, self).set_state(**kwargs)
|
||||
|
||||
def update(self):
|
||||
ip = _external_ip(query_url=self.query_url)
|
||||
with self.write_lock:
|
||||
self.ip = ip
|
||||
def update(self, old_ip):
|
||||
return _external_ip(query_url=self.query_url)
|
||||
|
||||
def render(self, **kwargs):
|
||||
if not hasattr(self, 'ip'):
|
||||
def render(self, ip, **kwargs):
|
||||
if not ip:
|
||||
return None
|
||||
return [{'contents': self.ip, 'divider_highlight_group': 'background:divider'}]
|
||||
return [{'contents': ip, 'divider_highlight_group': 'background:divider'}]
|
||||
|
||||
|
||||
external_ip = with_docstring(ExternalIpSegment(),
|
||||
@ -357,10 +357,9 @@ class WeatherSegment(ThreadedSegment):
|
||||
def set_state(self, location_query=None, **kwargs):
|
||||
self.location = location_query
|
||||
self.url = None
|
||||
self.condition = {}
|
||||
super(WeatherSegment, self).set_state(**kwargs)
|
||||
|
||||
def update(self):
|
||||
def update(self, old_weather):
|
||||
import json
|
||||
|
||||
if not self.url:
|
||||
@ -398,31 +397,31 @@ class WeatherSegment(ThreadedSegment):
|
||||
icon_names = ('unknown',)
|
||||
self.error('Unknown condition code: {0}', condition_code)
|
||||
|
||||
with self.write_lock:
|
||||
self.temp = temp
|
||||
self.icon_names = icon_names
|
||||
return (temp, icon_names)
|
||||
|
||||
def render(self, icons=None, unit='C', temp_format=None, temp_coldest=-30, temp_hottest=40, **kwargs):
|
||||
if not hasattr(self, 'icon_names'):
|
||||
def render(self, weather, icons=None, unit='C', temp_format=None, temp_coldest=-30, temp_hottest=40, **kwargs):
|
||||
if not weather:
|
||||
return None
|
||||
|
||||
for icon_name in self.icon_names:
|
||||
temp, icon_names = weather
|
||||
|
||||
for icon_name in icon_names:
|
||||
if icons:
|
||||
if icon_name in icons:
|
||||
icon = icons[icon_name]
|
||||
break
|
||||
else:
|
||||
icon = weather_conditions_icons[self.icon_names[-1]]
|
||||
icon = weather_conditions_icons[icon_names[-1]]
|
||||
|
||||
temp_format = temp_format or ('{temp:.0f}' + temp_units[unit])
|
||||
temp = temp_conversions[unit](self.temp)
|
||||
if self.temp <= temp_coldest:
|
||||
converted_temp = temp_conversions[unit](temp)
|
||||
if temp <= temp_coldest:
|
||||
gradient_level = 0
|
||||
elif self.temp >= temp_hottest:
|
||||
elif temp >= temp_hottest:
|
||||
gradient_level = 100
|
||||
else:
|
||||
gradient_level = (self.temp - temp_coldest) * 100.0 / (temp_hottest - temp_coldest)
|
||||
groups = ['weather_condition_' + icon_name for icon_name in self.icon_names] + ['weather_conditions', 'weather']
|
||||
gradient_level = (temp - temp_coldest) * 100.0 / (temp_hottest - temp_coldest)
|
||||
groups = ['weather_condition_' + icon_name for icon_name in icon_names] + ['weather_conditions', 'weather']
|
||||
return [
|
||||
{
|
||||
'contents': icon + ' ',
|
||||
@ -430,7 +429,7 @@ class WeatherSegment(ThreadedSegment):
|
||||
'divider_highlight_group': 'background:divider',
|
||||
},
|
||||
{
|
||||
'contents': temp_format.format(temp=temp),
|
||||
'contents': temp_format.format(temp=converted_temp),
|
||||
'highlight_group': ['weather_temp_gradient', 'weather_temp', 'weather'],
|
||||
'draw_divider': False,
|
||||
'divider_highlight_group': 'background:divider',
|
||||
|
@ -318,13 +318,13 @@ class RepositorySegment(KwWindowThreadedSegment):
|
||||
# FIXME os.getcwd() is not a proper variant for non-current buffers
|
||||
return segment_info['buffer'].name or os.getcwd()
|
||||
|
||||
def update(self):
|
||||
def update(self, *args):
|
||||
# .compute_state() is running only in this method, and only in one
|
||||
# thread, thus operations with .directories do not need write locks
|
||||
# (.render() method is not using .directories). If this is changed
|
||||
# .directories needs redesigning
|
||||
self.directories.clear()
|
||||
super(RepositorySegment, self).update()
|
||||
return super(RepositorySegment, self).update(*args)
|
||||
|
||||
def compute_state(self, path):
|
||||
repo = guess(path=path)
|
||||
|
@ -12,6 +12,7 @@ class Pl(object):
|
||||
self.prefix = None
|
||||
self.environ = {}
|
||||
self.home = None
|
||||
self.use_daemon_threads = True
|
||||
|
||||
def getcwd(self):
|
||||
if isinstance(self._cwd, Exception):
|
||||
|
Loading…
x
Reference in New Issue
Block a user