test_mutex.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. from panda3d.core import Mutex, ReMutex
  2. from panda3d import core
  3. from random import random
  4. import pytest
  5. def test_mutex_acquire_release():
  6. m = Mutex()
  7. m.acquire()
  8. # Assert that the lock is truly held now
  9. assert m.debug_is_locked()
  10. # Release the lock
  11. m.release()
  12. # Make sure the lock is properly released
  13. assert m.try_acquire()
  14. # Clean up
  15. m.release()
  16. def test_mutex_try_acquire():
  17. m = Mutex()
  18. # Trying to acquire the lock should succeed
  19. assert m.try_acquire()
  20. # Assert that the lock is truly held now
  21. assert m.debug_is_locked()
  22. # Clean up
  23. m.release()
  24. @pytest.mark.skipif(not core.Thread.is_threading_supported(),
  25. reason="Threading support disabled")
  26. def test_mutex_contention():
  27. # As a smoke test for mutexes, we just spawn a bunch of threads that do a
  28. # lot of mutexing and hope that we can catch any obvious issues with the
  29. # mutex implementation, especially when compiling with DEBUG_THREADS.
  30. m1 = Mutex()
  31. m2 = Mutex()
  32. m3 = Mutex()
  33. m4 = Mutex()
  34. def thread_acq_rel(m):
  35. for i in range(5000):
  36. m.acquire()
  37. m.release()
  38. def thread_nested():
  39. for i in range(5000):
  40. m1.acquire()
  41. m4.acquire()
  42. m4.release()
  43. m1.release()
  44. def thread_hand_over_hand():
  45. m1.acquire()
  46. for i in range(5000):
  47. m2.acquire()
  48. m1.release()
  49. m3.acquire()
  50. m2.release()
  51. m1.acquire()
  52. m3.release()
  53. m1.release()
  54. def thread_sleep(m):
  55. for i in range(250):
  56. m.acquire()
  57. core.Thread.sleep(random() * 0.003)
  58. m.release()
  59. threads = [
  60. core.PythonThread(thread_acq_rel, (m1,), "", ""),
  61. core.PythonThread(thread_acq_rel, (m2,), "", ""),
  62. core.PythonThread(thread_acq_rel, (m3,), "", ""),
  63. core.PythonThread(thread_acq_rel, (m4,), "", ""),
  64. core.PythonThread(thread_nested, (), "", ""),
  65. core.PythonThread(thread_nested, (), "", ""),
  66. core.PythonThread(thread_nested, (), "", ""),
  67. core.PythonThread(thread_hand_over_hand, (), "", ""),
  68. core.PythonThread(thread_hand_over_hand, (), "", ""),
  69. core.PythonThread(thread_sleep, (m1,), "", ""),
  70. core.PythonThread(thread_sleep, (m2,), "", ""),
  71. core.PythonThread(thread_sleep, (m3,), "", ""),
  72. core.PythonThread(thread_sleep, (m4,), "", ""),
  73. ]
  74. for thread in threads:
  75. thread.start(core.TP_normal, True)
  76. for thread in threads:
  77. thread.join()
  78. def test_remutex_acquire_release():
  79. m = ReMutex()
  80. m.acquire()
  81. m.acquire()
  82. m.release()
  83. m.release()
  84. def test_remutex_try_acquire():
  85. m = ReMutex()
  86. # Trying to acquire the lock should succeed
  87. assert m.try_acquire()
  88. # Should report being locked
  89. assert m.debug_is_locked()
  90. # Trying a second time should succeed
  91. assert m.try_acquire()
  92. # Should still report being locked
  93. assert m.debug_is_locked()
  94. # Clean up
  95. m.release()
  96. m.release()