Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

135 Zeilen
3.8KB

  1. """Implements the standard threading module, using greenthreads."""
  2. import eventlet
  3. from eventlet.green import thread
  4. from eventlet.green import time
  5. from eventlet.support import greenlets as greenlet
  6. import six
  7. __patched__ = ['_start_new_thread', '_allocate_lock',
  8. '_sleep', 'local', 'stack_size', 'Lock', 'currentThread',
  9. 'current_thread', '_after_fork', '_shutdown']
  10. if six.PY2:
  11. __patched__ += ['_get_ident']
  12. else:
  13. __patched__ += ['get_ident', '_set_sentinel']
  14. __orig_threading = eventlet.patcher.original('threading')
  15. __threadlocal = __orig_threading.local()
  16. __patched_enumerate = None
  17. eventlet.patcher.inject(
  18. 'threading',
  19. globals(),
  20. ('thread' if six.PY2 else '_thread', thread),
  21. ('time', time))
  22. _count = 1
  23. class _GreenThread(object):
  24. """Wrapper for GreenThread objects to provide Thread-like attributes
  25. and methods"""
  26. def __init__(self, g):
  27. global _count
  28. self._g = g
  29. self._name = 'GreenThread-%d' % _count
  30. _count += 1
  31. def __repr__(self):
  32. return '<_GreenThread(%s, %r)>' % (self._name, self._g)
  33. def join(self, timeout=None):
  34. return self._g.wait()
  35. def getName(self):
  36. return self._name
  37. get_name = getName
  38. def setName(self, name):
  39. self._name = str(name)
  40. set_name = setName
  41. name = property(getName, setName)
  42. ident = property(lambda self: id(self._g))
  43. def isAlive(self):
  44. return True
  45. is_alive = isAlive
  46. daemon = property(lambda self: True)
  47. def isDaemon(self):
  48. return self.daemon
  49. is_daemon = isDaemon
  50. __threading = None
  51. def _fixup_thread(t):
  52. # Some third-party packages (lockfile) will try to patch the
  53. # threading.Thread class with a get_name attribute if it doesn't
  54. # exist. Since we might return Thread objects from the original
  55. # threading package that won't get patched, let's make sure each
  56. # individual object gets patched too our patched threading.Thread
  57. # class has been patched. This is why monkey patching can be bad...
  58. global __threading
  59. if not __threading:
  60. __threading = __import__('threading')
  61. if (hasattr(__threading.Thread, 'get_name') and
  62. not hasattr(t, 'get_name')):
  63. t.get_name = t.getName
  64. return t
  65. def current_thread():
  66. global __patched_enumerate
  67. g = greenlet.getcurrent()
  68. if not g:
  69. # Not currently in a greenthread, fall back to standard function
  70. return _fixup_thread(__orig_threading.current_thread())
  71. try:
  72. active = __threadlocal.active
  73. except AttributeError:
  74. active = __threadlocal.active = {}
  75. g_id = id(g)
  76. t = active.get(g_id)
  77. if t is not None:
  78. return t
  79. # FIXME: move import from function body to top
  80. # (jaketesler@github) Furthermore, I was unable to have the current_thread() return correct results from
  81. # threading.enumerate() unless the enumerate() function was a) imported at runtime using the gross __import__() call
  82. # and b) was hot-patched using patch_function().
  83. # https://github.com/eventlet/eventlet/issues/172#issuecomment-379421165
  84. if __patched_enumerate is None:
  85. __patched_enumerate = eventlet.patcher.patch_function(__import__('threading').enumerate)
  86. found = [th for th in __patched_enumerate() if th.ident == g_id]
  87. if found:
  88. return found[0]
  89. # Add green thread to active if we can clean it up on exit
  90. def cleanup(g):
  91. del active[g_id]
  92. try:
  93. g.link(cleanup)
  94. except AttributeError:
  95. # Not a GreenThread type, so there's no way to hook into
  96. # the green thread exiting. Fall back to the standard
  97. # function then.
  98. t = _fixup_thread(__orig_threading.current_thread())
  99. else:
  100. t = active[g_id] = _GreenThread(g)
  101. return t
  102. currentThread = current_thread