test_mutex.py 3.5 KB

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