| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- /******************************************************************************/
- #include "stdafx.h"
- namespace EE{
- /******************************************************************************
- 'PtrCounter' value means:
- -1 =unloaded
- 0 =loaded and listed in delay remove
- >=1 =loaded and not listed in delay remove
- /******************************************************************************/
- #define DELAY_REMOVE_STEP (1.0f/8) // number of steps per 'delay_remove' time to check for element removal
- struct DelayRemove
- {
- PtrCounter *data;
- void (*unload)(Ptr elm);
- Flt time;
- };
- static Memc<DelayRemove> DelayRemoves;
- static Flt _DelayRemoveTime, DelayRemoveCheck;
- /******************************************************************************/
- static Int FindDelayRemove(Ptr data) {REPA(DelayRemoves)if(DelayRemoves[i].data==data)return i; return -1;}
- static void RemoveFromDelayRemove(Ptr data) {DelayRemoves.remove(FindDelayRemove(data));}
- static void ProcessDelayRemove(Bool always)
- {
- if(DelayRemoves.elms())
- {
- DelayRemoveCheck=Time.appTime()+_DelayRemoveTime*DELAY_REMOVE_STEP; // perform next check at this time
- REPA(DelayRemoves)
- {
- DelayRemove &remove=DelayRemoves[i];
- 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)
- {
- PtrCounter *data=remove.data; void (*unload)(Ptr elm)=remove.unload; DelayRemoves.remove(i); // access before removal and remove afterwards
- DEBUG_ASSERT(data->_ptrs==0, "'ProcessDelayRemove' '_ptrs' should be zero");
- data->_ptrs=-1; unload(data); // set '_ptrs' before calling 'unload'
- }
- }
- }
- }
- void DelayRemoveNow () { ProcessDelayRemove(true );}
- void DelayRemoveUpdate() {if(DelayRemoves.elms() && Time.appTime()>=DelayRemoveCheck)ProcessDelayRemove(false);}
- void DelayRemoveTime (Flt time)
- {
- Bool adjust_existing=true;
- MAX(time, 0); if(time!=_DelayRemoveTime)
- {
- Flt delta=time-_DelayRemoveTime; // how much are we increasing the delay
- _DelayRemoveTime =time; // set new value
- DelayRemoveCheck+=delta*DELAY_REMOVE_STEP; // adjust check time
- if(adjust_existing)REPAO(DelayRemoves).time+=delta; // adjust element removal times
- DelayRemoveUpdate();
- }
- }
- /******************************************************************************/
- 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
- void PtrCounter::decRef(void (*unload)(Ptr elm))
- {
- if(this) // this method is called for null objects too
- {
- DEBUG_ASSERT(_ptrs>0, "'PtrCounter.decRef' Decreasing '_ptrs' when it's already zero");
- if(!--_ptrs) // if there are no more pointers accessing this element
- {
- if(_DelayRemoveTime>0) // use delay remove
- {
- DelayRemove &delay_remove=DelayRemoves.New();
- delay_remove.data =this;
- delay_remove.unload=unload;
- delay_remove.time =Time.appTime()+_DelayRemoveTime;
- }else // remove now
- {
- _ptrs=-1; unload(this); // set '_ptrs' before calling 'unload'
- }
- }
- }
- }
- void PtrCounter::incRef(Bool (*load)(Ptr elm))
- {
- if(this) // this method is called for null objects too
- switch(_ptrs)
- {
- case -1: _ptrs=1; load(this); break; // if unloaded , adjust '_ptrs' before anything else
- case 0: _ptrs=1; RemoveFromDelayRemove(this); break; // if delay remove, adjust '_ptrs' before anything else
- default: _ptrs++; break;
- }
- }
- /******************************************************************************/
- }
- /******************************************************************************/
|