All Downloads are FREE. Search and download functionalities are using the official Maven repository.

brooklyn.util.mutex.SemaphoreWithOwners Maven / Gradle / Ivy

There is a newer version: 0.7.0-M1
Show newest version
package brooklyn.util.mutex;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

import com.google.common.collect.ImmutableList;

/** a subclass of Semaphore which requires the same thread to release as created it,
 * and which tracks who created and released the semaphores */
public class SemaphoreWithOwners extends Semaphore {
    public SemaphoreWithOwners(String name) {
        this(name, 1, true);
    }
    public SemaphoreWithOwners(String name, int permits, boolean fair) {
        super(permits, fair);
        this.name = name;
    }
    private static final long serialVersionUID = -5303474637353009454L;
    final private List owningThreads = new ArrayList();
    final private Set requestingThreads = new LinkedHashSet();

    @Override
    public void acquire() throws InterruptedException {
        try {
            onRequesting();
            super.acquire();
            onAcquired(1);
        } finally {
            onRequestFinished();
        }
    }
    @Override
    public void acquire(int permits) throws InterruptedException {
        try {
            onRequesting();
            super.acquire(permits);
            onAcquired(permits);
        } finally {
            onRequestFinished();
        }
    }
    @Override
    public void acquireUninterruptibly() {
        try {
            onRequesting();
            super.acquireUninterruptibly();
            onAcquired(1);
        } finally {
            onRequestFinished();
        }
    }
    @Override
    public void acquireUninterruptibly(int permits) {
        try {
            onRequesting();
            super.acquireUninterruptibly(permits);
            onAcquired(permits);
        } finally {
            onRequestFinished();
        }
    }

    @Override
    public boolean tryAcquire() {
        try {
            onRequesting();
            if (super.tryAcquire()) {
                onAcquired(1);
                return true;
            }
            return false;
        } finally {
            onRequestFinished();
        }
    }
    @Override
    public boolean tryAcquire(int permits) {
        try {
            onRequesting();
            if (super.tryAcquire(permits)) {
                onAcquired(permits);
                return true;
            }
            return false;
        } finally {
            onRequestFinished();
        }
    }
    @Override
    public boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException {
        try {
            onRequesting();
            if (super.tryAcquire(permits, timeout, unit)) {
                onAcquired(permits);
                return true;
            }
            return false;
        } finally {
            onRequestFinished();
        }
    }
    @Override
    public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException {
        try {
            onRequesting();
            if (super.tryAcquire(timeout, unit)) {
                onAcquired(1);
                return true;
            }
            return false;
        } finally {
            onRequestFinished();
        }
    }

    protected synchronized void onAcquired(int permits) {
        for (int i=0; i getOwningThreads() {
        return ImmutableList.copyOf(owningThreads);
    }
    /** unmodifiable view of threads requesting access (blocked or briefly trying to acquire);
     * this is guaranteed to be cleared _after_ getOwners 
     * (synchronizing on this class while reading both fields will give canonical access) */
    public synchronized List getRequestingThreads() {
        return ImmutableList.copyOf(requestingThreads);
    }
    
    @Override
    public synchronized String toString() {
        return super.toString()+"["+name+"; description="+description+"; owning="+owningThreads+"; requesting="+requestingThreads+"]";
    }
    
    /** Indicate that the calling thread is going to acquire or tryAcquire, 
     * in order to set up the semaphore's isInUse() value appropriately for certain checks.
     * It *must* do so after invoking this method. */ 
    public void indicateCallingThreadWillRequest() {
        requestingThreads.add(Thread.currentThread());
    }
    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy