001package com.hammurapi.store; 002 003import java.util.concurrent.TimeUnit; 004import java.util.concurrent.atomic.AtomicInteger; 005import java.util.concurrent.locks.Condition; 006import java.util.concurrent.locks.Lock; 007 008/** 009 * Lock which acts on behalf of another lock and acquires its own lock only 010 * if the master lock is not held. This lock is used for executing one logical 011 * store operation in multiple threads. 012 * @author Pavel Vlasov 013 * 014 */ 015public class DeputyLock implements TrackingLock { 016 017 private Lock master; 018 private boolean masterLocked; 019 private AtomicInteger lockCounter = new AtomicInteger(0); 020 private boolean canNotBeLocked; 021 private String msg; 022 023 public DeputyLock(Lock master, boolean masterLocked, boolean canNotBeLocked, String msg) { 024 this.master = master; 025 this.masterLocked = masterLocked; 026 this.canNotBeLocked = canNotBeLocked; 027 this.msg = msg; 028 } 029 030 private void checkLockability() { 031 if (canNotBeLocked) { 032 throw new IllegalStateException(msg); 033 } 034 } 035 036 @Override 037 public void lock() { 038 if (!masterLocked) { 039 checkLockability(); 040 master.lock(); 041 lockCounter.incrementAndGet(); 042 } 043 } 044 045 @Override 046 public void lockInterruptibly() throws InterruptedException { 047 if (!masterLocked) { 048 checkLockability(); 049 master.lockInterruptibly(); 050 lockCounter.incrementAndGet(); 051 } 052 } 053 054 @Override 055 public boolean tryLock() { 056 if (masterLocked) { 057 return true; 058 } 059 checkLockability(); 060 if (master.tryLock()) { 061 lockCounter.incrementAndGet(); 062 return true; 063 } 064 return false; 065 } 066 067 @Override 068 public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { 069 if (masterLocked) { 070 return true; 071 } 072 checkLockability(); 073 if (master.tryLock(time, unit)) { 074 lockCounter.incrementAndGet(); 075 return true; 076 } 077 return false; 078 } 079 080 @Override 081 public void unlock() { 082 if (masterLocked) { 083 master.unlock(); 084 lockCounter.decrementAndGet(); 085 } 086 } 087 088 public boolean isLocked() { 089 return masterLocked || lockCounter.get()>0; 090 } 091 092 @Override 093 public Condition newCondition() { 094 return master.newCondition(); 095 } 096 097// public DeputyLock createDeputy() { 098// return new DeputyLock(this, isLocked(), canNotBeLocked, msg); 099// } 100 101}