// $Id: FairQueueAllocation.java,v 1.7 2007-07-03 13:51:31 tigran Exp $
package org.dcache.pool.classic;
import java.util.ArrayList;
import java.util.List;
import org.dcache.pool.repository.Account;
import org.dcache.pool.repository.Allocator;
/**
* Implementation of the SpaceMonitor interface, which serves requests
* in FIFO order.
*/
public class FairQueueAllocation
implements Allocator
{
private Account _account;
/**
* A list of threads waiting for space. Requests are served in the
* order they appear in this list.
*/
private final List<Thread> _list =
new ArrayList<>();
public FairQueueAllocation()
{
}
public synchronized void setAccount(Account account)
{
_account = account;
}
private synchronized void enqueue(Thread thread)
{
_list.add(thread);
}
private synchronized void dequeue(Thread thread)
{
_list.remove(thread);
notifyAll();
}
private synchronized void waitForTurn(Thread thread)
throws InterruptedException
{
while (_list.get(0) != thread) {
wait();
}
}
/**
* Allocate space. If not enough free space is available, the
* thread blocks until free space is made available.
*
* In case not enough space is available, a callback is triggered
* such that the sweeper knows that additional space is required.
*/
@Override
public void allocate(long space)
throws InterruptedException
{
if (space < 0) {
throw new IllegalArgumentException("Cannot allocate negative space");
}
final Thread self = Thread.currentThread();
enqueue(self);
try {
waitForTurn(self);
_account.allocate(space);
} finally {
dequeue(self);
}
}
@Override
public boolean allocateNow(long space)
throws InterruptedException
{
if (space < 0) {
throw new IllegalArgumentException("Cannot allocate negative space");
}
final Thread self = Thread.currentThread();
enqueue(self);
try {
waitForTurn(self);
return _account.allocateNow(space);
} finally {
dequeue(self);
}
}
@Override
public void free(long space)
{
_account.free(space);
}
}