package com.hammurapi.store;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;

/**
 * This lock acts on behalf of another lock and acquires its own locks
 * only if the master doesn't hold corresponding locks. This class is used
 * to distribute store operations to multiple threads/processes.
 * @author Pavel Vlasov
 *
 */
public class DeputyReadWriteLock implements ReadWriteLock {
	
	private DeputyLock readLock;
	private DeputyLock writeLock;
	
	public DeputyReadWriteLock(ReadWriteLock master, boolean readLocked, boolean writeLocked) {
		this.readLock = new DeputyLock(master.readLock(), readLocked || writeLocked, false, null);
		this.writeLock = new DeputyLock(master.writeLock(), writeLocked, !writeLocked && readLocked, "Read lock is already held, can't upgrade to write lock, locks can only be downgraded.");
	}
	
	protected DeputyReadWriteLock(DeputyLock readLock, DeputyLock writeLock) {
		this.readLock = readLock;
		this.writeLock = writeLock;
	}

	@Override
	public Lock readLock() {
		return readLock;
	}

	@Override
	public Lock writeLock() {
		return writeLock;
	}
	
	public DeputyReadWriteLock createDeputy() {
		return new DeputyReadWriteLock(this, readLock.isLocked() || writeLock.isLocked(), writeLock.isLocked());
	}

}
