MicroObjectRecycler.inl.h 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Gr/Vulkan/MicroObjectRecycler.h>
  6. namespace anki {
  7. template<typename T>
  8. inline void MicroObjectRecycler<T>::destroy()
  9. {
  10. LockGuard<Mutex> lock(m_mtx);
  11. for(U32 i = 0; i < m_objects.getSize(); ++i)
  12. {
  13. T* obj = m_objects[i];
  14. ANKI_ASSERT(obj);
  15. ANKI_ASSERT(!obj->getFence() || obj->getFence()->done());
  16. auto alloc = obj->getAllocator();
  17. alloc.deleteInstance(obj);
  18. #if ANKI_EXTRA_CHECKS
  19. --m_createdAndNotRecycled;
  20. #endif
  21. }
  22. m_objects.destroy(m_alloc);
  23. ANKI_ASSERT(m_createdAndNotRecycled == 0 && "Destroying the recycler while objects have not recycled yet");
  24. }
  25. template<typename T>
  26. inline void MicroObjectRecycler<T>::releaseFences()
  27. {
  28. for(U32 i = 0; i < m_objects.getSize(); ++i)
  29. {
  30. T& obj = *m_objects[i];
  31. if(obj.getFence() && obj.getFence()->done())
  32. {
  33. obj.getFence().reset(nullptr);
  34. }
  35. }
  36. }
  37. template<typename T>
  38. inline T* MicroObjectRecycler<T>::findToReuse()
  39. {
  40. T* out = nullptr;
  41. LockGuard<Mutex> lock(m_mtx);
  42. if(m_objects.getSize() > 0)
  43. {
  44. releaseFences();
  45. for(U32 i = 0; i < m_objects.getSize(); ++i)
  46. {
  47. if(!m_objects[i]->getFence())
  48. {
  49. out = m_objects[i];
  50. m_objects[i] = m_objects[m_objects.getSize() - 1];
  51. m_objects.popBack(m_alloc);
  52. break;
  53. }
  54. }
  55. }
  56. ANKI_ASSERT(out == nullptr || out->getRefcount().getNonAtomically() == 0);
  57. #if ANKI_EXTRA_CHECKS
  58. if(out == nullptr)
  59. {
  60. ++m_createdAndNotRecycled;
  61. }
  62. #endif
  63. return out;
  64. }
  65. template<typename T>
  66. inline void MicroObjectRecycler<T>::recycle(T* s)
  67. {
  68. ANKI_ASSERT(s);
  69. ANKI_ASSERT(s->getRefcount().getNonAtomically() == 0);
  70. LockGuard<Mutex> lock(m_mtx);
  71. releaseFences();
  72. m_objects.emplaceBack(m_alloc, s);
  73. }
  74. template<typename T>
  75. inline void MicroObjectRecycler<T>::trimCache()
  76. {
  77. LockGuard<Mutex> lock(m_mtx);
  78. releaseFences();
  79. DynamicArray<T*> aliveObjects;
  80. for(U32 i = 0; i < m_objects.getSize(); ++i)
  81. {
  82. T* obj = m_objects[i];
  83. ANKI_ASSERT(obj);
  84. ANKI_ASSERT(obj->getRefcount().getNonAtomically() == 0);
  85. if(obj->getFence())
  86. {
  87. // Can't delete it
  88. aliveObjects.emplaceBack(m_alloc, obj);
  89. }
  90. else
  91. {
  92. auto alloc = obj->getAllocator();
  93. alloc.deleteInstance(obj);
  94. #if ANKI_EXTRA_CHECKS
  95. --m_createdAndNotRecycled;
  96. #endif
  97. }
  98. }
  99. if(aliveObjects.getSize() > 0)
  100. {
  101. // Some alive, store the alive
  102. m_objects.destroy(m_alloc);
  103. m_objects = std::move(aliveObjects);
  104. }
  105. else if(aliveObjects.getSize() == 0 && m_objects.getSize() >= 0)
  106. {
  107. // All dead, destroy the array
  108. m_objects.destroy(m_alloc);
  109. }
  110. }
  111. } // end namespace anki