Files
deb-python-eventlet/eventlet/hubs/zeromq.py
Ben Ford b75e83a35c First stab at zeromq support. This consists of:
A new hub: This closely mirrors the poll hub with some of the internal logic changed to reflect zmq's flags.
A green module for zmq: This subclasses Context and Socket to ensure calls are non blocking.
A (very sparse) beginings of a test module.
An example: A melding of the pyzmq chat example and the eventlet telnet chat example.


TODO

zmq_poll chokes if the sockets passed to it come from different contexts. As context is the entry point to everything else then it would make sense to include a check in here that each thread has only one context instance. By context being the entry point I mean:

ctx = zmq.Context()
socket = ctx.socket(zmq.<type-of-socket>)

This call to socket is repeated for each socket you want and ctx must be the same one for each thread.

Tests. I'd like to get to the point f having all zmq socket pairs tested - and perhaps a nice benchmark suite too.
2010-09-20 07:08:27 +01:00

83 lines
2.5 KiB
Python

from eventlet import patcher
from eventlet.green import zmq
from eventlet.hubs import poll
from eventlet.hubs.hub import BaseHub, noop
from eventlet.hubs.poll import READ, WRITE
from eventlet.support import clear_sys_exc_info
import sys
time = patcher.original('time')
select = patcher.original('select')
sleep = time.sleep
EXC_MASK = zmq.POLLERR
READ_MASK = zmq.POLLIN
WRITE_MASK = zmq.POLLOUT
class Hub(poll.Hub):
def __init__(self, clock=time.time):
BaseHub.__init__(self, clock)
self.poll = zmq.Poller()
def register(self, fileno, new=False):
mask = 0
if self.listeners[READ].get(fileno):
mask |= READ_MASK
if self.listeners[WRITE].get(fileno):
mask |= WRITE_MASK
if mask:
self.poll.register(fileno, mask)
else:
self.poll.unregister(fileno)
def wait(self, seconds=None):
readers = self.listeners[READ]
writers = self.listeners[WRITE]
if not readers and not writers:
if seconds:
sleep(seconds)
return
try:
presult = self.do_poll(seconds)
except zmq.ZMQError, e:
# In the poll hub this part exists to special case some exceptions
# from socket. There may be some error numbers that wider use of
# this hub will throw up as needing special treatment so leaving
# this block and this comment as a remineder
raise
SYSTEM_EXCEPTIONS = self.SYSTEM_EXCEPTIONS
if self.debug_blocking:
self.block_detect_pre()
for fileno, event in presult:
try:
if event & READ_MASK:
readers.get(fileno, noop).cb(fileno)
if event & WRITE_MASK:
writers.get(fileno, noop).cb(fileno)
if event & EXC_MASK:
# zmq.POLLERR is returned for any error condition in the
# underlying fd (as passed through to poll/epoll)
readers.get(fileno, noop).cb(fileno)
writers.get(fileno, noop).cb(fileno)
except SYSTEM_EXCEPTIONS:
raise
except:
self.squelch_exception(fileno, sys.exc_info())
clear_sys_exc_info()
if self.debug_blocking:
self.block_detect_post()
# def do_poll(self, seconds):
# print 'poll: ', seconds
# if seconds < 0:
# seconds = 500
# return self.poll.poll(seconds)