Counted Pointer.cpp 3.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************
  5. 'PtrCounter' value means:
  6. -1 =unloaded
  7. 0 =loaded and listed in delay remove
  8. >=1 =loaded and not listed in delay remove
  9. /******************************************************************************/
  10. #define DELAY_REMOVE_STEP (1.0f/8) // number of steps per 'delay_remove' time to check for element removal
  11. struct DelayRemove
  12. {
  13. PtrCounter *data;
  14. void (*unload)(Ptr elm);
  15. Flt time;
  16. };
  17. static Memc<DelayRemove> DelayRemoves;
  18. static Flt _DelayRemoveTime, DelayRemoveCheck;
  19. /******************************************************************************/
  20. static Int FindDelayRemove(Ptr data) {REPA(DelayRemoves)if(DelayRemoves[i].data==data)return i; return -1;}
  21. static void RemoveFromDelayRemove(Ptr data) {DelayRemoves.remove(FindDelayRemove(data));}
  22. static void ProcessDelayRemove(Bool always)
  23. {
  24. if(DelayRemoves.elms())
  25. {
  26. DelayRemoveCheck=Time.appTime()+_DelayRemoveTime*DELAY_REMOVE_STEP; // perform next check at this time
  27. REPA(DelayRemoves)
  28. {
  29. DelayRemove &remove=DelayRemoves[i];
  30. if(always || Time.appTime()>=remove.time) // if always remove or enough time has passed (use >= so when having zero delay time then it will be processed immediately)
  31. {
  32. PtrCounter *data=remove.data; void (*unload)(Ptr elm)=remove.unload; DelayRemoves.remove(i); // access before removal and remove afterwards
  33. DEBUG_ASSERT(data->_ptrs==0, "'ProcessDelayRemove' '_ptrs' should be zero");
  34. data->_ptrs=-1; unload(data); // set '_ptrs' before calling 'unload'
  35. }
  36. }
  37. }
  38. }
  39. void DelayRemoveNow () { ProcessDelayRemove(true );}
  40. void DelayRemoveUpdate() {if(DelayRemoves.elms() && Time.appTime()>=DelayRemoveCheck)ProcessDelayRemove(false);}
  41. void DelayRemoveTime (Flt time)
  42. {
  43. Bool adjust_existing=true;
  44. MAX(time, 0); if(time!=_DelayRemoveTime)
  45. {
  46. Flt delta=time-_DelayRemoveTime; // how much are we increasing the delay
  47. _DelayRemoveTime =time; // set new value
  48. DelayRemoveCheck+=delta*DELAY_REMOVE_STEP; // adjust check time
  49. if(adjust_existing)REPAO(DelayRemoves).time+=delta; // adjust element removal times
  50. DelayRemoveUpdate();
  51. }
  52. }
  53. /******************************************************************************/
  54. PtrCounter::~PtrCounter() {if(_ptrs==0){_ptrs=-1; RemoveFromDelayRemove(this);}} // if object is being deleted, but it's marked to be removed later, then remove it from the list
  55. void PtrCounter::decRef(void (*unload)(Ptr elm))
  56. {
  57. if(this) // this method is called for null objects too
  58. {
  59. DEBUG_ASSERT(_ptrs>0, "'PtrCounter.decRef' Decreasing '_ptrs' when it's already zero");
  60. if(!--_ptrs) // if there are no more pointers accessing this element
  61. {
  62. if(_DelayRemoveTime>0) // use delay remove
  63. {
  64. DelayRemove &delay_remove=DelayRemoves.New();
  65. delay_remove.data =this;
  66. delay_remove.unload=unload;
  67. delay_remove.time =Time.appTime()+_DelayRemoveTime;
  68. }else // remove now
  69. {
  70. _ptrs=-1; unload(this); // set '_ptrs' before calling 'unload'
  71. }
  72. }
  73. }
  74. }
  75. void PtrCounter::incRef(Bool (*load)(Ptr elm))
  76. {
  77. if(this) // this method is called for null objects too
  78. switch(_ptrs)
  79. {
  80. case -1: _ptrs=1; load(this); break; // if unloaded , adjust '_ptrs' before anything else
  81. case 0: _ptrs=1; RemoveFromDelayRemove(this); break; // if delay remove, adjust '_ptrs' before anything else
  82. default: _ptrs++; break;
  83. }
  84. }
  85. /******************************************************************************/
  86. }
  87. /******************************************************************************/