export function getObjectRefCounter()

in packages/redux-dynamic-modules-core/src/Utils/RefCounter.ts [18:93]


export function getObjectRefCounter<T>(
    equals: (a: T, b: T) => boolean,
    retained?: (a: T) => boolean
): IRefCounter<T> {
    if (!equals) {
        equals = (a, b) => a === b;
    }

    if(!retained) {
        retained = () => false;
    }
    const objects: T[] = [];
    const counts: number[] = [];
    return {
        /**
         * Gets ref count of given T
         */
        getCount: (obj: T): number => {
            if (obj === undefined || obj === null) {
                return 0;
            }

            let index = objects.findIndex(o => o && equals(o, obj));
            if (index === -1) {
                return 0;
            }
            return counts[index];
        },
        /**
         * Add given T or increments ref count
         */
        add: (obj: T): void => {
            if (obj === undefined || obj === null) {
                return;
            }

            let index = objects.findIndex(o => o && equals(o, obj));
            let count = 1;
            if (index === -1) {
                index = objects.length;
                objects.push(obj);
            } else {
                count = counts[index] + 1;
            }

            // If item is retained then keep it for inifinty
            if (retained(obj)) {
                count = Infinity;
            }
            
            counts[index] = count;
        },
        /**
         * Decreases ref count for given T, if refcount reaches to zero removes the T and returns true
         */
        remove: (obj: T): boolean => {
            if (retained(obj)) {
                return false;
            }
            
            let index = objects.findIndex(o => o && equals(o, obj));
            if (index === -1) {
                return false;
            }

            if (counts[index] === 1) {
                delete objects[index];
                delete counts[index];
                return true;
            }

            counts[index] = counts[index] - 1;
            return false;
        },
    };
}