/pypy/rlib/rstacklet.py

https://github.com/nicolaslara/pypy · Python · 126 lines · 102 code · 17 blank · 7 comment · 19 complexity · 354ccde6835b91f5d1089687b4be2f76 MD5 · raw file

  1. from pypy.rlib import _rffi_stacklet as _c
  2. from pypy.rlib import jit
  3. from pypy.rlib.objectmodel import we_are_translated
  4. from pypy.rpython.lltypesystem import lltype, llmemory
  5. DEBUG = False
  6. class StackletThread(object):
  7. @jit.dont_look_inside
  8. def __init__(self, config):
  9. self._gcrootfinder = _getgcrootfinder(config, we_are_translated())
  10. self._thrd = _c.newthread()
  11. if not self._thrd:
  12. raise MemoryError
  13. self._thrd_deleter = StackletThreadDeleter(self._thrd)
  14. if DEBUG:
  15. assert debug.sthread is None, "multithread debug support missing"
  16. debug.sthread = self
  17. @jit.dont_look_inside
  18. def new(self, callback, arg=llmemory.NULL):
  19. if DEBUG:
  20. callback = _debug_wrapper(callback)
  21. h = self._gcrootfinder.new(self, callback, arg)
  22. if DEBUG:
  23. debug.add(h)
  24. return h
  25. new._annspecialcase_ = 'specialize:arg(1)'
  26. @jit.dont_look_inside
  27. def switch(self, stacklet):
  28. if DEBUG:
  29. debug.remove(stacklet)
  30. h = self._gcrootfinder.switch(self, stacklet)
  31. if DEBUG:
  32. debug.add(h)
  33. return h
  34. @jit.dont_look_inside
  35. def destroy(self, stacklet):
  36. if DEBUG:
  37. debug.remove(stacklet)
  38. self._gcrootfinder.destroy(self, stacklet)
  39. def is_empty_handle(self, stacklet):
  40. # note that "being an empty handle" and being equal to
  41. # "get_null_handle()" may be the same, or not; don't rely on it
  42. return self._gcrootfinder.is_empty_handle(stacklet)
  43. def get_null_handle(self):
  44. return self._gcrootfinder.get_null_handle()
  45. class StackletThreadDeleter(object):
  46. # quick hack: the __del__ is on another object, so that
  47. # if the main StackletThread ends up in random circular
  48. # references, on pypy deletethread() is only called
  49. # when all that circular reference mess is gone.
  50. def __init__(self, thrd):
  51. self._thrd = thrd
  52. def __del__(self):
  53. thrd = self._thrd
  54. if thrd:
  55. self._thrd = lltype.nullptr(_c.thread_handle.TO)
  56. _c.deletethread(thrd)
  57. # ____________________________________________________________
  58. def _getgcrootfinder(config, translated):
  59. if translated:
  60. assert config is not None, ("you have to pass a valid config, "
  61. "e.g. from 'driver.config'")
  62. if config is not None:
  63. assert config.translation.continuation, (
  64. "stacklet: you have to translate with --continuation")
  65. if (config is None or
  66. config.translation.gc in ('ref', 'boehm', 'none')): # for tests
  67. gcrootfinder = 'n/a'
  68. else:
  69. gcrootfinder = config.translation.gcrootfinder
  70. gcrootfinder = gcrootfinder.replace('/', '_')
  71. module = __import__('pypy.rlib._stacklet_%s' % gcrootfinder,
  72. None, None, ['__doc__'])
  73. return module.gcrootfinder
  74. _getgcrootfinder._annspecialcase_ = 'specialize:memo'
  75. class StackletDebugError(Exception):
  76. pass
  77. class Debug(object):
  78. def __init__(self):
  79. self.sthread = None
  80. self.active = []
  81. def _freeze_(self):
  82. self.__init__()
  83. return False
  84. def add(self, h):
  85. if not self.sthread.is_empty_handle(h):
  86. if h == self.sthread.get_null_handle():
  87. raise StackletDebugError("unexpected null handle")
  88. self.active.append(h)
  89. def remove(self, h):
  90. try:
  91. i = self.active.index(h)
  92. except ValueError:
  93. if self.sthread.is_empty_handle(h):
  94. msg = "empty stacklet handle"
  95. elif h == self.sthread.get_null_handle():
  96. msg = "unexpected null handle"
  97. else:
  98. msg = "double usage of handle %r" % (h,)
  99. raise StackletDebugError(msg)
  100. del self.active[i]
  101. debug = Debug()
  102. def _debug_wrapper(callback):
  103. def wrapper(h, arg):
  104. debug.add(h)
  105. h = callback(h, arg)
  106. debug.remove(h)
  107. return h
  108. return wrapper
  109. _debug_wrapper._annspecialcase_ = 'specialize:memo'