package allen.town.podcast.core.sync;

import java.util.concurrent.locks.ReentrantLock;

import io.reactivex.Completable;
import io.reactivex.schedulers.Schedulers;

public class LockingAsyncExecutor {

    static final ReentrantLock lock = new ReentrantLock();

    /**
     * Take the lock and execute runnable (to prevent changes to preferences being lost when enqueueing while sync is
     * in progress). If the lock is free, the runnable is directly executed in the calling thread to prevent overhead.
     */
    public static void executeLockedAsync(Runnable runnable) {
        if (lock.tryLock()) {
            try {
                runnable.run();
            } finally {
                lock.unlock();
            }
        } else {
            Completable.fromRunnable(() -> {
                lock.lock();
                try {
                    runnable.run();
                } finally {
                    lock.unlock();
                }
            }).subscribeOn(Schedulers.io())
                    .subscribe();
        }
    }
}
