package com.crm.rely.backend.util;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

public class SynchronizedKey {

    private static Map<String, ReentrantLock>  mutexCache = new ConcurrentHashMap<>();

    public static void exec(String key, Runnable statement) {
        ReentrantLock mutexKey = null;
        ReentrantLock mutexInCache;
        do {
            if (mutexKey != null) {
                mutexKey.unlock();
            }
            mutexKey = mutexCache.computeIfAbsent(key, k -> new ReentrantLock());

            mutexKey.lock();
            mutexInCache = mutexCache.get(key);

        } while (mutexInCache == null || mutexKey != mutexInCache);

        try {
            statement.run();
        } finally {
            if (mutexKey.getQueueLength() == 0) {
                mutexCache.remove(key);
            }
            mutexKey.unlock();
        }
    }
}
