您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

188 行
5.5KB

  1. import sys
  2. import traceback
  3. import types
  4. from eventlet.support import greenlets as greenlet
  5. import six
  6. from eventlet.hubs.hub import BaseHub, READ, WRITE
  7. try:
  8. import event
  9. except ImportError:
  10. event = None
  11. def is_available():
  12. return event is not None
  13. class event_wrapper(object):
  14. def __init__(self, impl=None, seconds=None):
  15. self.impl = impl
  16. self.seconds = seconds
  17. def __repr__(self):
  18. if self.impl is not None:
  19. return repr(self.impl)
  20. else:
  21. return object.__repr__(self)
  22. def __str__(self):
  23. if self.impl is not None:
  24. return str(self.impl)
  25. else:
  26. return object.__str__(self)
  27. def cancel(self):
  28. if self.impl is not None:
  29. self.impl.delete()
  30. self.impl = None
  31. @property
  32. def pending(self):
  33. return bool(self.impl and self.impl.pending())
  34. class Hub(BaseHub):
  35. SYSTEM_EXCEPTIONS = (KeyboardInterrupt, SystemExit)
  36. def __init__(self):
  37. super(Hub, self).__init__()
  38. event.init()
  39. self.signal_exc_info = None
  40. self.signal(
  41. 2,
  42. lambda signalnum, frame: self.greenlet.parent.throw(KeyboardInterrupt))
  43. self.events_to_add = []
  44. def dispatch(self):
  45. loop = event.loop
  46. while True:
  47. for e in self.events_to_add:
  48. if e is not None and e.impl is not None and e.seconds is not None:
  49. e.impl.add(e.seconds)
  50. e.seconds = None
  51. self.events_to_add = []
  52. result = loop()
  53. if getattr(event, '__event_exc', None) is not None:
  54. # only have to do this because of bug in event.loop
  55. t = getattr(event, '__event_exc')
  56. setattr(event, '__event_exc', None)
  57. assert getattr(event, '__event_exc') is None
  58. six.reraise(t[0], t[1], t[2])
  59. if result != 0:
  60. return result
  61. def run(self):
  62. while True:
  63. try:
  64. self.dispatch()
  65. except greenlet.GreenletExit:
  66. break
  67. except self.SYSTEM_EXCEPTIONS:
  68. raise
  69. except:
  70. if self.signal_exc_info is not None:
  71. self.schedule_call_global(
  72. 0, greenlet.getcurrent().parent.throw, *self.signal_exc_info)
  73. self.signal_exc_info = None
  74. else:
  75. self.squelch_timer_exception(None, sys.exc_info())
  76. def abort(self, wait=True):
  77. self.schedule_call_global(0, self.greenlet.throw, greenlet.GreenletExit)
  78. if wait:
  79. assert self.greenlet is not greenlet.getcurrent(
  80. ), "Can't abort with wait from inside the hub's greenlet."
  81. self.switch()
  82. def _getrunning(self):
  83. return bool(self.greenlet)
  84. def _setrunning(self, value):
  85. pass # exists for compatibility with BaseHub
  86. running = property(_getrunning, _setrunning)
  87. def add(self, evtype, fileno, real_cb, real_tb, mac):
  88. # this is stupid: pyevent won't call a callback unless it's a function,
  89. # so we have to force it to be one here
  90. if isinstance(real_cb, types.BuiltinMethodType):
  91. def cb(_d):
  92. real_cb(_d)
  93. else:
  94. cb = real_cb
  95. if evtype is READ:
  96. evt = event.read(fileno, cb, fileno)
  97. elif evtype is WRITE:
  98. evt = event.write(fileno, cb, fileno)
  99. return super(Hub, self).add(evtype, fileno, evt, real_tb, mac)
  100. def signal(self, signalnum, handler):
  101. def wrapper():
  102. try:
  103. handler(signalnum, None)
  104. except:
  105. self.signal_exc_info = sys.exc_info()
  106. event.abort()
  107. return event_wrapper(event.signal(signalnum, wrapper))
  108. def remove(self, listener):
  109. super(Hub, self).remove(listener)
  110. listener.cb.delete()
  111. def remove_descriptor(self, fileno):
  112. for lcontainer in six.itervalues(self.listeners):
  113. listener = lcontainer.pop(fileno, None)
  114. if listener:
  115. try:
  116. listener.cb.delete()
  117. except self.SYSTEM_EXCEPTIONS:
  118. raise
  119. except:
  120. traceback.print_exc()
  121. def schedule_call_local(self, seconds, cb, *args, **kwargs):
  122. current = greenlet.getcurrent()
  123. if current is self.greenlet:
  124. return self.schedule_call_global(seconds, cb, *args, **kwargs)
  125. event_impl = event.event(_scheduled_call_local, (cb, args, kwargs, current))
  126. wrapper = event_wrapper(event_impl, seconds=seconds)
  127. self.events_to_add.append(wrapper)
  128. return wrapper
  129. schedule_call = schedule_call_local
  130. def schedule_call_global(self, seconds, cb, *args, **kwargs):
  131. event_impl = event.event(_scheduled_call, (cb, args, kwargs))
  132. wrapper = event_wrapper(event_impl, seconds=seconds)
  133. self.events_to_add.append(wrapper)
  134. return wrapper
  135. def _version_info(self):
  136. baseversion = event.__version__
  137. return baseversion
  138. def _scheduled_call(event_impl, handle, evtype, arg):
  139. cb, args, kwargs = arg
  140. try:
  141. cb(*args, **kwargs)
  142. finally:
  143. event_impl.delete()
  144. def _scheduled_call_local(event_impl, handle, evtype, arg):
  145. cb, args, kwargs, caller_greenlet = arg
  146. try:
  147. if not caller_greenlet.dead:
  148. cb(*args, **kwargs)
  149. finally:
  150. event_impl.delete()