commit bdf6dacdc536957e0cbdfdb758fe1f884d3c5850
parent c7994d542e17cf67618cebfe205dc08165f4a739
Author: Kris Maglione <kris@suckless.org>
Date: Thu, 1 Jul 2010 21:45:27 -0400
[python] Fix some deadlock issues.
Diffstat:
4 files changed, 96 insertions(+), 60 deletions(-)
diff --git a/alternative_wmiircs/python/pygmi/event.py b/alternative_wmiircs/python/pygmi/event.py
@@ -164,7 +164,7 @@ class Keys(object):
"""
self.modes = {}
self.modelist = []
- self._set_mode('main', False)
+ self.mode = 'main'
self.defs = {}
events.bind(Key=self.dispatch)
@@ -179,17 +179,18 @@ class Keys(object):
}
self.modelist.append(mode)
- def _set_mode(self, mode, execute=True):
+ mode = property(lambda self: self._mode,
+ doc="The current mode for which to dispatch keys")
+ @mode.setter
+ def mode(self, mode):
self._add_mode(mode)
self._mode = mode
self._keys = dict((k % self.defs, v) for k, v in
self.modes[mode]['keys'].items() +
self.modes[mode]['import'].items());
- if execute:
+ if hasattr(self, 'defs'):
client.write('/keys', '\n'.join(self._keys.keys()) + '\n')
- mode = property(lambda self: self._mode, _set_mode,
- doc="The current mode for which to dispatch keys")
@prop(doc="Returns a short help text describing the bound keys in all modes")
def help(self):
diff --git a/alternative_wmiircs/python/pygmi/fs.py b/alternative_wmiircs/python/pygmi/fs.py
@@ -11,6 +11,7 @@ __all__ = ('wmii', 'Tags', 'Tag', 'Area', 'Frame', 'Client',
'Button', 'Colors', 'Color', 'Toggle', 'Always', 'Never')
spacere = re.compile(r'\s')
+sentinel = {}
class utf8(object):
def __str__(self):
@@ -67,7 +68,6 @@ class Ctl(object):
tuples, each containing a decoder and encoder function for the
property's plain text value.
"""
- sentinel = {}
ctl_types = {}
ctl_hasid = False
ctl_open = 'aopen'
@@ -312,14 +312,14 @@ class liveprop(object):
self.get = get
self.attr = str(self)
def __get__(self, area, cls):
- if getattr(area, self.attr, None) is not None:
+ if getattr(area, self.attr, sentinel) is not sentinel:
return getattr(area, self.attr)
return self.get(area)
def __set__(self, area, val):
setattr(area, self.attr, val)
class Area(object):
- def __init__(self, tag, ord, screen='sel', offset=None, width=None, height=None, frames=None):
+ def __init__(self, tag, ord, screen='sel', offset=sentinel, width=sentinel, height=sentinel, frames=sentinel):
self.tag = tag
if ':' in str(ord):
screen, ord = ord.split(':', 2)
@@ -344,17 +344,20 @@ class Area(object):
@property
def spec(self):
- return '%s:%s' % (self.screen, self.ord)
+ if self.screen is not None:
+ return '%s:%s' % (self.screen, self.ord)
+ return self.ord
- def _get_mode(self):
+ @property
+ def mode(self):
for k, v in self.tag.iteritems():
if k == 'colmode':
v = v.split(' ')
if v[0] == self.ord:
return v[1]
- mode = property(
- _get_mode,
- lambda self, val: self.tag.set('colmode %s' % self.spec, val))
+ @mode.setter
+ def mode(self, val):
+ self.tag['colmode %s' % self.spec] = val
def grow(self, dir, amount=None):
self.tag.grow(self, dir, amount)
@@ -364,7 +367,7 @@ class Area(object):
class Frame(object):
live = False
- def __init__(self, client, area=None, ord=None, offset=None, height=None):
+ def __init__(self, client, area=sentinel, ord=sentinel, offset=sentinel, height=sentinel):
self.client = client
self.ord = ord
self.offset = offset
@@ -414,21 +417,24 @@ class Tag(Dir):
dir = ' '.join(dir)
return dir
- def _set_selected(self, frame):
+ @property
+ def selected(self):
+ return tuple(self['select'].split(' '))
+ @selected.setter
+ def selected(self, frame):
if not isinstance(frame, basestring) or ' ' not in frame:
frame = self.framespec(frame)
self['select'] = frame
- selected = property(lambda self: tuple(self['select'].split(' ')),
- _set_selected)
- def _get_selclient(self):
+ @property
+ def selclient(self):
for k, v in self.iteritems():
if k == 'select' and 'client' in v:
return Client(v.split(' ')[1])
return None
- selclient = property(_get_selclient,
- lambda self, val: self.set('select',
- self.framespec(val)))
+ @selclient.setter
+ def selclient(self, val):
+ self['select'] = self.framespec(val)
@property
def selcol(self):
@@ -437,9 +443,9 @@ class Tag(Dir):
@property
def index(self):
areas = []
- for l in [l.split(' ')
+ for l in (l.split(' ')
for l in client.readlines('%s/index' % self.path)
- if l]:
+ if l):
if l[0] == '#':
m = re.match(r'(?:(\d+):)?(\d+|~)', l[1])
if m.group(2) == '~':
@@ -447,7 +453,7 @@ class Tag(Dir):
height=l[3], frames=[])
else:
area = Area(tag=self, screen=m.group(1) or 0,
- ord=m.group(2), offset=l[2], width=l[3],
+ height=None, ord=m.group(2), offset=l[2], width=l[3],
frames=[])
areas.append(area)
i = 0
@@ -797,12 +803,12 @@ class Tags(object):
self.tags[tag].button.label = urgent and '*' + tag or tag
def next(self, reverse=False):
- tags = [t for t in wmii.tags if t.id not in self.ignore]
+ tags = [t for t in wmii.tags if t not in self.ignore]
tags.append(tags[0])
if reverse:
tags.reverse()
for i in range(0, len(tags)):
- if tags[i] == self.sel:
+ if tags[i] == self.sel.id:
return tags[i+1]
return self.sel
diff --git a/alternative_wmiircs/python/pygmi/monitor.py b/alternative_wmiircs/python/pygmi/monitor.py
@@ -107,7 +107,12 @@ class Monitor(object):
return None
_active = True
- def _set_active(self, val):
+ @property
+ def active(self):
+ return self._active
+
+ @active.setter
+ def active(self, val):
with self.lock:
self._active = bool(val)
if val:
@@ -115,8 +120,4 @@ class Monitor(object):
else:
self.button.remove()
- active = property(
- lambda self: self._active,
- _set_active)
-
# vim:se sts=4 sw=4 et:
diff --git a/alternative_wmiircs/python/pyxp/mux.py b/alternative_wmiircs/python/pyxp/mux.py
@@ -39,6 +39,9 @@ class Mux(object):
self.maxtag = maxtag
self.muxer = None
+ self.async_mux = Queue(self.mux)
+ self.async_dispatch = Queue(self.async_dispatch)
+
if isinstance(con, basestring):
con = dial(con)
self.fd = con
@@ -48,8 +51,8 @@ class Mux(object):
def mux(self, rpc):
try:
- rpc.waiting = True
self.lock.acquire()
+ rpc.waiting = True
while self.muxer and self.muxer != rpc and rpc.data is None:
rpc.wait()
@@ -69,7 +72,7 @@ class Mux(object):
self.lock.acquire()
self.electmuxer()
except Exception, e:
- traceback.print_exc(sys.stdout)
+ traceback.print_exc(sys.stderr)
if self.flush:
self.flush(self, rpc.data)
raise e
@@ -77,36 +80,26 @@ class Mux(object):
if self.lock._is_owned():
self.lock.release()
- if rpc.async:
- if callable(rpc.async):
- rpc.async(self, rpc.data)
- else:
- return rpc.data
+ return rpc.data
def rpc(self, dat, async=None):
rpc = self.newrpc(dat, async)
if async:
- with self.lock:
- if self.muxer is None:
- self.electmuxer()
+ self.async_mux.push(rpc)
else:
return self.mux(rpc)
+ def async_dispatch(self, rpc):
+ self.async_mux.pop(rpc)
+ rpc.async(self, rpc.data)
+
def electmuxer(self):
- async = None
for rpc in self.queue:
- if self.muxer != rpc:
- if rpc.async:
- async = rpc
- else:
- self.muxer = rpc
- rpc.notify()
- return
+ if self.muxer != rpc and rpc.waiting:
+ self.muxer = rpc
+ rpc.notify()
+ return
self.muxer = None
- if async:
- self.muxer = async
- t = Thread(target=self.mux, args=(async,))
- t.start()
def dispatch(self, dat):
tag = dat.tag
@@ -156,8 +149,7 @@ class Mux(object):
data += self.fd.recv(len - 4)
return self.process(data)
except Exception, e:
- traceback.print_exc(sys.stdout)
- print repr(data)
+ traceback.print_exc(sys.stderr)
return None
def newrpc(self, dat, async=None):
@@ -181,14 +173,50 @@ class Rpc(Condition):
self.mux = mux
self.orig = data
self.data = None
- self.waiting = False
self.async = async
+ self.waiting = False
def dispatch(self, data=None):
self.data = data
- if not self.async or self.waiting:
- self.notify()
- elif callable(self.async):
- Thread(target=self.async, args=(self.mux, data)).start()
+ self.notify()
+ if callable(self.async):
+ self.mux.async_dispatch(self)
+
+class Queue(Thread):
+ def __init__(self, op):
+ super(Queue, self).__init__()
+ self.cond = Condition()
+ self.op = op
+ self.queue = []
+ self.daemon = True
+
+ def __call__(self, item):
+ return self.push(item)
+
+ def push(self, item):
+ with self.cond:
+ self.queue.append(item)
+ if not self.is_alive():
+ self.start()
+ self.cond.notify()
+ def pop(self, item):
+ with self.cond:
+ if item in self.queue:
+ self.queue.remove(item)
+ return True
+ return False
+
+ def run(self):
+ self.cond.acquire()
+ while True:
+ while self.queue:
+ item = self.queue.pop(0)
+ self.cond.release()
+ try:
+ self.op(item)
+ except Exception, e:
+ traceback.print_exc(sys.stderr)
+ self.cond.acquire()
+ self.cond.wait()
# vim:se sts=4 sw=4 et: