MicroObjectRecycler.inl.h 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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. {
  8. template<typename T>
  9. inline void MicroObjectRecycler<T>::destroy()
  10. {
  11. LockGuard<Mutex> lock(m_mtx);
  12. for(U32 i = 0; i < m_objects.getSize(); ++i)
  13. {
  14. T* obj = m_objects[i];
  15. ANKI_ASSERT(obj);
  16. ANKI_ASSERT(!obj->getFence() || obj->getFence()->done());
  17. auto alloc = obj->getAllocator();
  18. alloc.deleteInstance(obj);
  19. #if ANKI_EXTRA_CHECKS
  20. --m_createdAndNotRecycled;
  21. #endif
  22. }
  23. m_objects.destroy(m_alloc);
  24. ANKI_ASSERT(m_createdAndNotRecycled == 0 && "Destroying the recycler while objects have not recycled yet");
  25. }
  26. template<typename T>
  27. inline void MicroObjectRecycler<T>::releaseFences()
  28. {
  29. for(U32 i = 0; i < m_objects.getSize(); ++i)
  30. {
  31. T& obj = *m_objects[i];
  32. if(obj.getFence() && obj.getFence()->done())
  33. {
  34. obj.getFence().reset(nullptr);
  35. }
  36. }
  37. }
  38. template<typename T>
  39. inline T* MicroObjectRecycler<T>::findToReuse()
  40. {
  41. T* out = nullptr;
  42. LockGuard<Mutex> lock(m_mtx);
  43. if(m_objects.getSize() > 0)
  44. {
  45. releaseFences();
  46. for(U32 i = 0; i < m_objects.getSize(); ++i)
  47. {
  48. if(!m_objects[i]->getFence())
  49. {
  50. out = m_objects[i];
  51. m_objects[i] = m_objects[m_objects.getSize() - 1];
  52. m_objects.popBack(m_alloc);
  53. break;
  54. }
  55. }
  56. }
  57. ANKI_ASSERT(out == nullptr || out->getRefcount().getNonAtomically() == 0);
  58. #if ANKI_EXTRA_CHECKS
  59. if(out == nullptr)
  60. {
  61. ++m_createdAndNotRecycled;
  62. }
  63. #endif
  64. return out;
  65. }
  66. template<typename T>
  67. inline void MicroObjectRecycler<T>::recycle(T* s)
  68. {
  69. ANKI_ASSERT(s);
  70. ANKI_ASSERT(s->getRefcount().getNonAtomically() == 0);
  71. LockGuard<Mutex> lock(m_mtx);
  72. releaseFences();
  73. m_objects.emplaceBack(m_alloc, s);
  74. }
  75. template<typename T>
  76. inline void MicroObjectRecycler<T>::trimCache()
  77. {
  78. LockGuard<Mutex> lock(m_mtx);
  79. releaseFences();
  80. DynamicArray<T*> newObjects;
  81. for(U32 i = 0; i < m_objects.getSize(); ++i)
  82. {
  83. T* obj = m_objects[i];
  84. ANKI_ASSERT(obj);
  85. ANKI_ASSERT(obj->getRefcount().getNonAtomically() == 0);
  86. if(obj->getFence())
  87. {
  88. // Can't delete it
  89. newObjects.emplaceBack(m_alloc, obj);
  90. }
  91. else
  92. {
  93. auto alloc = obj->getAllocator();
  94. alloc.deleteInstance(obj);
  95. }
  96. }
  97. if(newObjects.getSize() > 0)
  98. {
  99. m_objects.destroy(m_alloc);
  100. m_objects = std::move(newObjects);
  101. }
  102. }
  103. } // end namespace anki