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