@doegis/core
Version:
DOE GIS API
3 lines (1 loc) • 2.35 kB
JavaScript
class e{get largestRange(){return this._largestRange}constructor(e){this._largestRange=null,this._parent=e,this._updateLargestRange()}rangeCreated(e){(!this._largestRange||e.count>this._largestRange.count)&&(this._largestRange=e)}rangeResized(e,t){e===this._largestRange?e.count<t&&this._updateLargestRange():(!this._largestRange||e.count>this._largestRange.count)&&(this._largestRange=e)}findBestRange(e){let t=this._parent._freeHead,n=null;for(;null!==t;)t.count>=e&&(!n||t.count-e<n.count-e)&&(n=t),t=t.next;return n}findAdjacentRanges(e,t){let n=!0,r=!1,s=null,o=this._parent._freeHead;for(;n&&!r;){const a=null!==s?s.from+s.count:0,l=null!==o?o.from:this._parent._size;e>=a&&e+t<=l?(n=!1,r=!0):null!==o?(s=o,o=o.next):n=!1}return[s,o]}_updateLargestRange(){let e=null,t=this._parent._freeHead;for(;null!==t;)(!e||t.count>e.count)&&(e=t),t=t.next;this._largestRange=e}}class t{constructor(t,n){this._allocated=0,this._size=t,this._freeHead=t>0?{from:0,count:t,prev:null,next:null}:null,this._bookKeeper=n||new e(this),this._freeHead&&this._bookKeeper.rangeCreated(this._freeHead)}allocate(e){const n=this._bookKeeper.findBestRange(e);if(null==n)return-1;const r=n.from,s=n.count;if(n.from+=e,n.count-=e,this._bookKeeper.rangeResized(n,r,s),this._allocated+=e,0===n.count){const e=null!==n.prev?this._freeHead:n.next;t._removeRange(n),this._freeHead=e}return r}free(e,n){const[r,s]=this._bookKeeper.findAdjacentRanges(e,n),o={from:e,count:n,prev:r??null,next:s??null};if(null!=r&&(r.next=o),null!=s&&(s.prev=o),this._bookKeeper.rangeCreated(o),this._allocated-=n,null!=s&&o.from+o.count===s.from){const e=o.from,n=o.count;t._fuse(o,s),t._removeRange(s),this._bookKeeper.rangeResized(o,e,n),this._bookKeeper.rangeResized(s,void 0,0)}if(null!=r&&r.from+r.count===o.from){const e=r.from,n=r.count;t._fuse(r,o),t._removeRange(o),this._bookKeeper.rangeResized(r,e,n),this._bookKeeper.rangeResized(o,void 0,0)}this._freeHead=null!==o.prev?this._freeHead:o}get fragmentation(){const e=this._size-this._allocated;if(0===e)return 0;return 1-this._bookKeeper.largestRange.count/e}static _removeRange(e){null!==e.prev?null!==e.next?(e.prev.next=e.next,e.next.prev=e.prev):e.prev.next=null:null!==e.next&&(e.next.prev=null)}static _fuse(e,t){e.count+=t.count,e.next=t.next,t.from+=t.count,t.count=0,null!==t.next&&(t.next.prev=e)}}export{t as FreeList};