[pytango] 19/26: Fix SF bug #747: event callback gets called in tango thread in gevent mode
Sandor Bodo-Merle
sbodomerle-guest at moszumanska.debian.org
Thu Sep 28 19:16:14 UTC 2017
This is an automated email from the git hooks/post-receive script.
sbodomerle-guest pushed a commit to annotated tag v8.1.8
in repository pytango.
commit 0000172d9f190e3dddd0dcf7357a34f7fbd3a62d
Author: Jose Tiago Coutinho Macara <coutinho at esrf.fr>
Date: Wed Oct 21 17:10:44 2015 +0200
Fix SF bug #747: event callback gets called in tango thread in gevent mode
- Create an event_loop greenlet. Callback code is transferred to this
greenlet for execution
- Increase PyTango patch version number since this introduces a difference
in behavior
---
src/boost/python/device_proxy.py | 9 ++++++---
src/boost/python/green.py | 26 +++++++++++++++++++++++++-
src/boost/python/release.py | 2 +-
src/boost/python/tango_gevent.py | 28 +++++++++++++++++++++++++++-
4 files changed, 59 insertions(+), 6 deletions(-)
diff --git a/src/boost/python/device_proxy.py b/src/boost/python/device_proxy.py
index 8b8206d..bd43fb7 100644
--- a/src/boost/python/device_proxy.py
+++ b/src/boost/python/device_proxy.py
@@ -32,7 +32,7 @@ from .utils import is_pure_str, is_non_str_seq, is_integer
from .utils import seq_2_StdStringVector, StdStringVector_2_seq
from .utils import seq_2_DbData, DbData_2_dict
from .utils import document_method as __document_method
-from .green import result, submit, green, get_green_mode
+from .green import result, submit, green, green_cb, get_green_mode, get_event_loop
_UNSUBSCRIBE_LIFETIME = 60
@@ -96,6 +96,9 @@ def get_device_proxy(*args, **kwargs):
wait = kwargs.pop('wait', True)
timeout = kwargs.pop('timeout', None)
+ # make sure the event loop is initialized
+ get_event_loop(green_mode)
+
d = submit(green_mode, DeviceProxy, *args, **kwargs)
return result(d, green_mode, wait=wait, timeout=timeout)
@@ -837,10 +840,10 @@ def __DeviceProxy__subscribe_event (self, attr_name, event_type, cb_or_queuesize
if isinstance(cb_or_queuesize, collections.Callable):
cb = __CallBackPushEvent()
- cb.push_event = cb_or_queuesize
+ cb.push_event = green_cb(cb_or_queuesize, self.get_green_mode())
elif hasattr(cb_or_queuesize, "push_event") and isinstance(cb_or_queuesize.push_event, collections.Callable):
cb = __CallBackPushEvent()
- cb.push_event = cb_or_queuesize.push_event
+ cb.push_event = green_cb(cb_or_queuesize.push_event, self.get_green_mode())
elif is_integer(cb_or_queuesize):
cb = cb_or_queuesize # queuesize
else:
diff --git a/src/boost/python/green.py b/src/boost/python/green.py
index c36c2ff..a0ec36f 100644
--- a/src/boost/python/green.py
+++ b/src/boost/python/green.py
@@ -14,7 +14,8 @@ __all__ = ["get_green_mode", "set_green_mode",
"get_synch_executor", "synch_submit",
"get_gevent_executor", "gevent_submit",
"get_futures_executor", "futures_submit",
- "result", "submitable", "green"]
+ "get_event_loop", "get_gevent_event_loop",
+ "result", "submitable", "green", "green_cb"]
__docformat__ = "restructuredtext"
@@ -24,6 +25,7 @@ from functools import wraps
from ._PyTango import GreenMode
from .tango_gevent import get_global_executor as get_gevent_executor
from .tango_gevent import submit as gevent_submit
+from .tango_gevent import get_event_loop as get_gevent_event_loop
from .tango_futures import get_global_executor as get_futures_executor
from .tango_futures import submit as futures_submit
@@ -92,6 +94,10 @@ __submit_map = {
GreenMode.Gevent: gevent_submit,
}
+__event_loop_map = {
+ GreenMode.Gevent: get_gevent_event_loop,
+}
+
def get_executor(mode):
return __executor_map[mode]()
@@ -103,6 +109,11 @@ def submit(mode, fn, *args, **kwargs):
spawn = submit
+def get_event_loop(mode):
+ f = __event_loop_map.get(mode)
+ if f:
+ return f()
+
def result(value, green_mode, wait=True, timeout=None):
if wait and not green_mode is GreenMode.Synchronous:
if green_mode == GreenMode.Futures:
@@ -165,3 +176,16 @@ def green(fn):
return result(ret, green_mode, wait=wait, timeout=timeout)
return greener
+def green_cb(fn, green_mode=None):
+ """return a green verion of the given callback."""
+
+ @wraps(fn)
+ def greener(*args, **kwargs):
+ event_loop = get_event_loop(green_mode)
+ if event_loop is None:
+ fn(*args, **kwargs)
+ else:
+ event_loop.submit(fn, *args, **kwargs)
+
+ return greener
+
diff --git a/src/boost/python/release.py b/src/boost/python/release.py
index b13d7ff..4c9d904 100644
--- a/src/boost/python/release.py
+++ b/src/boost/python/release.py
@@ -40,7 +40,7 @@ class Release:
- keywords : (seq<str>) list of keywords
- license : (str) the license"""
name = 'PyTango'
- version_info = (8, 1, 7, 'dev', 0)
+ version_info = (8, 1, 8, 'dev', 0)
version = '.'.join(map(str, version_info[:3]))
version_long = version + ''.join(map(str, version_info[3:]))
version_description = 'This version implements the C++ Tango 8.1 API.'
diff --git a/src/boost/python/tango_gevent.py b/src/boost/python/tango_gevent.py
index 60919eb..4fa6a6e 100644
--- a/src/boost/python/tango_gevent.py
+++ b/src/boost/python/tango_gevent.py
@@ -13,7 +13,8 @@ from __future__ import absolute_import
import sys
import types
-__all__ = ["get_global_threadpool", "get_global_executor", "submit", "spawn"]
+__all__ = ["get_global_threadpool", "get_global_executor",
+ "get_event_loop", "submit", "spawn"]
def get_global_threadpool():
import gevent
@@ -67,3 +68,28 @@ def spawn(fn, *args, **kwargs):
get_global_executor = get_global_threadpool
submit = spawn
+
+__event_loop = None
+
+def get_event_loop():
+ global __event_loop
+ if __event_loop is None:
+ import gevent
+ import gevent.queue
+
+ def loop(queue):
+ while True:
+ event = queue.get()
+ f, args, kwargs = event
+ try:
+ f(*args, **kwargs)
+ except Exception as e:
+ sys.excepthook(*sys.exc_info())
+
+ def submit(fn, *args, **kwargs):
+ queue.put((fn, args, kwargs))
+
+ queue = gevent.queue.Queue()
+ __event_loop = gevent.spawn(loop, queue)
+ __event_loop.submit = submit
+ return __event_loop
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/pytango.git
More information about the debian-science-commits
mailing list