ObserverPtr.cpp 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. #include "../../Include/RmlUi/Core/ObserverPtr.h"
  2. #include "Pool.h"
  3. namespace Rml {
  4. struct ObserverPtrData {
  5. bool is_shutdown = false;
  6. Pool<Detail::ObserverPtrBlock> block_pool{128, true};
  7. };
  8. static ObserverPtrData* observer_ptr_data = nullptr;
  9. void Detail::DeallocateObserverPtrBlockIfEmpty(ObserverPtrBlock* block)
  10. {
  11. RMLUI_ASSERT(block->num_observers >= 0);
  12. if (block->num_observers == 0 && block->pointed_to_object == nullptr)
  13. {
  14. observer_ptr_data->block_pool.DestroyAndDeallocate(block);
  15. if (observer_ptr_data->is_shutdown && observer_ptr_data->block_pool.GetNumAllocatedObjects() == 0)
  16. {
  17. delete observer_ptr_data;
  18. observer_ptr_data = nullptr;
  19. }
  20. }
  21. }
  22. void Detail::InitializeObserverPtrPool()
  23. {
  24. if (!observer_ptr_data)
  25. observer_ptr_data = new ObserverPtrData;
  26. observer_ptr_data->is_shutdown = false;
  27. }
  28. void Detail::ShutdownObserverPtrPool()
  29. {
  30. if (observer_ptr_data->block_pool.GetNumAllocatedObjects() == 0)
  31. {
  32. delete observer_ptr_data;
  33. observer_ptr_data = nullptr;
  34. }
  35. else
  36. {
  37. // This pool must outlive all other global variables that derive from EnableObserverPtr. This even includes user
  38. // variables which we have no control over. So if there are any objects still alive, let the pool garbage
  39. // collect itself when all references to it are gone. It is somewhat unreasonable to expect that no observer
  40. // pointers remain, particularly because that means no objects derived from Rml::EventListener can be alive in
  41. // user space, which can be a hassle to ensure and is otherwise pretty innocent.
  42. observer_ptr_data->is_shutdown = true;
  43. }
  44. }
  45. Detail::ObserverPtrBlock* Detail::AllocateObserverPtrBlock()
  46. {
  47. return observer_ptr_data->block_pool.AllocateAndConstruct();
  48. }
  49. } // namespace Rml