package com.koushikdutta.async; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; public class AsyncSemaphore { Semaphore semaphore = new Semaphore(0); public void acquire() throws InterruptedException { ThreadQueue threadQueue = ThreadQueue.getOrCreateThreadQueue(Thread.currentThread()); AsyncSemaphore last = threadQueue.waiter; threadQueue.waiter = this; Semaphore queueSemaphore = threadQueue.queueSemaphore; try { if (semaphore.tryAcquire()) return; while (true) { // run the queue while (true) { Runnable run = threadQueue.remove(); if (run == null) break; // Log.i(LOGTAG, "Pumping for AsyncSemaphore"); run.run(); } int permits = Math.max(1, queueSemaphore.availablePermits()); queueSemaphore.acquire(permits); if (semaphore.tryAcquire()) break; } } finally { threadQueue.waiter = last; } } public boolean tryAcquire(long timeout, TimeUnit timeunit) throws InterruptedException { long timeoutMs = TimeUnit.MILLISECONDS.convert(timeout, timeunit); ThreadQueue threadQueue = ThreadQueue.getOrCreateThreadQueue(Thread.currentThread()); AsyncSemaphore last = threadQueue.waiter; threadQueue.waiter = this; Semaphore queueSemaphore = threadQueue.queueSemaphore; try { if (semaphore.tryAcquire()) return true; long start = System.currentTimeMillis(); do { // run the queue while (true) { Runnable run = threadQueue.remove(); if (run == null) break; // Log.i(LOGTAG, "Pumping for AsyncSemaphore"); run.run(); } int permits = Math.max(1, queueSemaphore.availablePermits()); if (!queueSemaphore.tryAcquire(permits, timeoutMs, TimeUnit.MILLISECONDS)) return false; if (semaphore.tryAcquire()) return true; } while (System.currentTimeMillis() - start < timeoutMs); return false; } finally { threadQueue.waiter = last; } } public void release() { semaphore.release(); ThreadQueue.release(this); } }