Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

threadable.py 3.2KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. # -*- test-case-name: twisted.python.test_threadable -*-
  2. # Copyright (c) Twisted Matrix Laboratories.
  3. # See LICENSE for details.
  4. """
  5. A module to provide some very basic threading primitives, such as
  6. synchronization.
  7. """
  8. from functools import wraps
  9. class DummyLock:
  10. """
  11. Hack to allow locks to be unpickled on an unthreaded system.
  12. """
  13. def __reduce__(self):
  14. return (unpickle_lock, ())
  15. def unpickle_lock():
  16. if threadingmodule is not None:
  17. return XLock()
  18. else:
  19. return DummyLock()
  20. unpickle_lock.__safe_for_unpickling__ = True # type: ignore[attr-defined]
  21. def _synchPre(self):
  22. if "_threadable_lock" not in self.__dict__:
  23. _synchLockCreator.acquire()
  24. if "_threadable_lock" not in self.__dict__:
  25. self.__dict__["_threadable_lock"] = XLock()
  26. _synchLockCreator.release()
  27. self._threadable_lock.acquire()
  28. def _synchPost(self):
  29. self._threadable_lock.release()
  30. def _sync(klass, function):
  31. @wraps(function)
  32. def sync(self, *args, **kwargs):
  33. _synchPre(self)
  34. try:
  35. return function(self, *args, **kwargs)
  36. finally:
  37. _synchPost(self)
  38. return sync
  39. def synchronize(*klasses):
  40. """
  41. Make all methods listed in each class' synchronized attribute synchronized.
  42. The synchronized attribute should be a list of strings, consisting of the
  43. names of methods that must be synchronized. If we are running in threaded
  44. mode these methods will be wrapped with a lock.
  45. """
  46. if threadingmodule is not None:
  47. for klass in klasses:
  48. for methodName in klass.synchronized:
  49. sync = _sync(klass, klass.__dict__[methodName])
  50. setattr(klass, methodName, sync)
  51. def init(with_threads=1):
  52. """Initialize threading.
  53. Don't bother calling this. If it needs to happen, it will happen.
  54. """
  55. global threaded, _synchLockCreator, XLock
  56. if with_threads:
  57. if not threaded:
  58. if threadingmodule is not None:
  59. threaded = True
  60. class XLock(threadingmodule._RLock):
  61. def __reduce__(self):
  62. return (unpickle_lock, ())
  63. _synchLockCreator = XLock()
  64. else:
  65. raise RuntimeError(
  66. "Cannot initialize threading, platform lacks thread support"
  67. )
  68. else:
  69. if threaded:
  70. raise RuntimeError("Cannot uninitialize threads")
  71. else:
  72. pass
  73. _dummyID = object()
  74. def getThreadID():
  75. if threadingmodule is None:
  76. return _dummyID
  77. return threadingmodule.current_thread().ident
  78. def isInIOThread():
  79. """Are we in the thread responsible for I/O requests (the event loop)?"""
  80. return ioThread == getThreadID()
  81. def registerAsIOThread():
  82. """Mark the current thread as responsible for I/O requests."""
  83. global ioThread
  84. ioThread = getThreadID()
  85. ioThread = None
  86. threaded = False
  87. # Define these globals which might be overwritten in init().
  88. _synchLockCreator = None
  89. XLock = None
  90. try:
  91. import threading as _threadingmodule
  92. except ImportError:
  93. threadingmodule = None
  94. else:
  95. threadingmodule = _threadingmodule
  96. init(True)
  97. __all__ = ["isInIOThread", "registerAsIOThread", "getThreadID", "XLock"]