Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
net.openhft.chronicle.algo.locks.VanillaReadWriteUpdateWithWaitsLockingStrategy Maven / Gradle / Ivy
/*
* Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.openhft.chronicle.algo.locks;
import net.openhft.chronicle.algo.bytes.Access;
import net.openhft.chronicle.algo.bytes.ReadAccess;
import static java.nio.ByteOrder.LITTLE_ENDIAN;
import static java.nio.ByteOrder.nativeOrder;
public final class VanillaReadWriteUpdateWithWaitsLockingStrategy
extends AbstractReadWriteLockingStrategy
implements ReadWriteUpdateWithWaitsLockingStrategy {
static final long COUNT_WORD_OFFSET = 0L;
static final long WAIT_WORD_OFFSET = COUNT_WORD_OFFSET + 4L;
static final int COUNT_WORD_SHIFT = nativeOrder() == LITTLE_ENDIAN ? 0 : 32;
static final int WAIT_WORD_SHIFT = nativeOrder() == LITTLE_ENDIAN ? 32 : 0;
static final int READ_BITS = 30;
static final int MAX_READ = (1 << READ_BITS) - 1;
static final int READ_MASK = MAX_READ;
static final int READ_PARTY = 1;
static final int UPDATE_PARTY = 1 << READ_BITS;
static final int WRITE_LOCKED_COUNT_WORD = UPDATE_PARTY << 1;
static final int MAX_WAIT = Integer.MAX_VALUE;
static final int WAIT_PARTY = 1;
private static final long UNSIGNED_INT_MASK = 0xFFFFFFFFL;
private static final ReadWriteUpdateWithWaitsLockingStrategy INSTANCE =
new VanillaReadWriteUpdateWithWaitsLockingStrategy();
private VanillaReadWriteUpdateWithWaitsLockingStrategy() {
}
public static ReadWriteUpdateWithWaitsLockingStrategy instance() {
return INSTANCE;
}
private static long getLockWord(ReadAccess access, T t, long offset) {
return access.readVolatileLong(t, offset);
}
private static boolean casLockWord(
Access access, T t, long offset, long expected, long x) {
return access.compareAndSwapLong(t, offset, expected, x);
}
private static int countWord(long lockWord) {
return (int) (lockWord >> COUNT_WORD_SHIFT);
}
private static int waitWord(long lockWord) {
return (int) (lockWord >> WAIT_WORD_SHIFT);
}
private static long lockWord(int countWord, int waitWord) {
return ((((long) countWord) & UNSIGNED_INT_MASK) << COUNT_WORD_SHIFT) |
((((long) waitWord) & UNSIGNED_INT_MASK) << WAIT_WORD_SHIFT);
}
private static int getCountWord(Access access, T t, long offset) {
return access.readVolatileInt(t, offset + COUNT_WORD_OFFSET);
}
private static boolean casCountWord(
Access access, T t, long offset, int expected, int x) {
return access.compareAndSwapInt(t, offset + COUNT_WORD_OFFSET, expected, x);
}
private static void putCountWord(
Access access, T t, long offset, int countWord) {
access.writeOrderedInt(t, offset + COUNT_WORD_OFFSET, countWord);
}
private static boolean writeLocked(int countWord) {
return countWord == WRITE_LOCKED_COUNT_WORD;
}
private static boolean updateLocked(int countWord) {
return (countWord & UPDATE_PARTY) != 0;
}
private static void checkUpdateLocked(int countWord) {
if (!updateLocked(countWord))
throw new IllegalMonitorStateException("Expected update lock");
}
private static int readCount(int countWord) {
return countWord & READ_MASK;
}
private static void checkReadLocked(int countWord) {
if (readCount(countWord) <= 0)
throw new IllegalMonitorStateException("Expected read lock");
}
private static void checkReadCountForIncrement(int countWord) {
if (readCount(countWord) == MAX_READ) {
throw new IllegalMonitorStateException(
"Lock count reached the limit of " + MAX_READ);
}
}
private static int getWaitWord(Access access, T t, long offset) {
return access.readVolatileInt(t, offset + WAIT_WORD_OFFSET);
}
private static boolean casWaitWord(
Access access, T t, long offset, int expected, int x) {
return access.compareAndSwapInt(t, offset + WAIT_WORD_OFFSET, expected, x);
}
private static void checkWaitWordForIncrement(int waitWord) {
if (waitWord == MAX_WAIT) {
throw new IllegalMonitorStateException(
"Wait count reached the limit of " + MAX_WAIT);
}
}
private static void checkWaitWordForDecrement(int waitWord) {
if (waitWord == 0) {
throw new IllegalMonitorStateException(
"Wait count underflowed");
}
}
private static boolean tryWriteLockAndDeregisterWait0(
Access access, T t, long offset, long lockWord) {
int waitWord = waitWord(lockWord);
checkWaitWordForDecrement(waitWord);
return casLockWord(access, t, offset, lockWord,
lockWord(WRITE_LOCKED_COUNT_WORD, waitWord - WAIT_PARTY));
}
private static boolean checkExclusiveUpdateLocked(int countWord) {
checkUpdateLocked(countWord);
return countWord == UPDATE_PARTY;
}
private static void checkWriteLockedAndPut(
Access access, T t, long offset, int countWord) {
if (!casCountWord(access, t, offset, WRITE_LOCKED_COUNT_WORD, countWord))
throw new IllegalMonitorStateException("Expected write lock");
}
@Override
public long resetState() {
return 0L;
}
@Override
public void reset(Access access, T t, long offset) {
access.writeOrderedLong(t, offset, 0L);
}
@Override
public void resetKeepingWaits(Access access, T t, long offset) {
putCountWord(access, t, offset, 0);
}
@Override
public boolean tryReadLock(Access access, T t, long offset) {
long lockWord = getLockWord(access, t, offset);
int countWord = countWord(lockWord);
if (!writeLocked(countWord) && waitWord(lockWord) == 0) {
checkReadCountForIncrement(countWord);
if (casCountWord(access, t, offset, countWord, countWord + READ_PARTY))
return true;
}
return false;
}
@Override
public boolean tryUpgradeReadToUpdateLock(Access access, T t, long offset) {
int countWord = getCountWord(access, t, offset);
checkReadLocked(countWord);
return !updateLocked(countWord) &&
casCountWord(access, t, offset, countWord, countWord - READ_PARTY + UPDATE_PARTY);
}
@Override
public boolean tryUpgradeReadToWriteLock(Access access, T t, long offset) {
if (casCountWord(access, t, offset, READ_PARTY, WRITE_LOCKED_COUNT_WORD)) {
return true;
} else {
int countWord = getCountWord(access, t, offset);
checkReadLocked(countWord);
return false;
}
}
@Override
public boolean tryUpgradeReadToWriteLockAndDeregisterWait(
Access access, T t, long offset) {
long lockWord = getLockWord(access, t, offset);
int countWord = countWord(lockWord);
checkReadLocked(countWord);
return countWord == READ_PARTY &&
tryWriteLockAndDeregisterWait0(access, t, offset, lockWord);
}
@Override
public boolean tryUpdateLock(Access access, T t, long offset) {
long lockWord = getLockWord(access, t, offset);
int countWord = countWord(lockWord);
if (!updateLocked(countWord) && !writeLocked(countWord) && waitWord(lockWord) == 0) {
if (casCountWord(access, t, offset, countWord, countWord + UPDATE_PARTY))
return true;
}
return false;
}
@Override
public boolean tryWriteLock(Access access, T t, long offset) {
return casCountWord(access, t, offset, 0, WRITE_LOCKED_COUNT_WORD);
}
@Override
public boolean tryWriteLockAndDeregisterWait(
Access access, T t, long offset) {
long lockWord = getLockWord(access, t, offset);
int countWord = countWord(lockWord);
return countWord == 0 && tryWriteLockAndDeregisterWait0(access, t, offset, lockWord);
}
@Override
public void registerWait(Access access, T t, long offset) {
while (true) {
int waitWord = getWaitWord(access, t, offset);
checkWaitWordForIncrement(waitWord);
if (casWaitWord(access, t, offset, waitWord, waitWord + WAIT_PARTY))
return;
}
}
@Override
public void deregisterWait(Access access, T t, long offset) {
while (true) {
int waitWord = getWaitWord(access, t, offset);
checkWaitWordForDecrement(waitWord);
if (casWaitWord(access, t, offset, waitWord, waitWord - WAIT_PARTY))
return;
}
}
@Override
public boolean tryUpgradeUpdateToWriteLock(Access access, T t, long offset) {
if (casCountWord(access, t, offset, UPDATE_PARTY, WRITE_LOCKED_COUNT_WORD)) {
return true;
} else {
int countWord = getCountWord(access, t, offset);
checkUpdateLocked(countWord);
return false;
}
}
@Override
public boolean tryUpgradeUpdateToWriteLockAndDeregisterWait(
Access access, T t, long offset) {
long lockWord = getLockWord(access, t, offset);
int countWord = countWord(lockWord);
return checkExclusiveUpdateLocked(countWord) &&
tryWriteLockAndDeregisterWait0(access, t, offset, lockWord);
}
@Override
public void readUnlock(Access access, T t, long offset) {
while (true) {
int countWord = getCountWord(access, t, offset);
checkReadLocked(countWord);
if (casCountWord(access, t, offset, countWord, countWord - READ_PARTY))
return;
}
}
@Override
public void updateUnlock(Access access, T t, long offset) {
while (true) {
int countWord = getCountWord(access, t, offset);
checkUpdateLocked(countWord);
if (casCountWord(access, t, offset, countWord, countWord - UPDATE_PARTY)) {
return;
}
}
}
@Override
public void downgradeUpdateToReadLock(Access access, T t, long offset) {
while (true) {
int countWord = getCountWord(access, t, offset);
checkUpdateLocked(countWord);
checkReadCountForIncrement(countWord);
if (casCountWord(access, t, offset, countWord, countWord - UPDATE_PARTY + READ_PARTY)) {
return;
}
}
}
@Override
public void writeUnlock(Access access, T t, long offset) {
checkWriteLockedAndPut(access, t, offset, 0);
}
@Override
public void downgradeWriteToUpdateLock(Access access, T t, long offset) {
checkWriteLockedAndPut(access, t, offset, UPDATE_PARTY);
}
@Override
public boolean isUpdateLocked(long state) {
return updateLocked(countWord(state));
}
@Override
public void downgradeWriteToReadLock(Access access, T t, long offset) {
checkWriteLockedAndPut(access, t, offset, READ_PARTY);
}
@Override
public long getState(ReadAccess access, T t, long offset) {
return getLockWord(access, t, offset);
}
@Override
public int readLockCount(long state) {
return readCount(countWord(state));
}
@Override
public boolean isWriteLocked(long state) {
return writeLocked(countWord(state));
}
@Override
public int waitCount(long state) {
return waitWord(state);
}
@Override
public boolean isLocked(long state) {
return countWord(state) != 0;
}
@Override
public int lockCount(long state) {
int countWord = countWord(state);
int lockCount = readCount(countWord);
if (lockCount > 0) {
return lockCount + (updateLocked(countWord) ? 1 : 0);
} else {
return writeLocked(countWord) ? 1 : 0;
}
}
@Override
public String toString(long state) {
return "[read locks = " + readLockCount(state) +
", update locked = " + isUpdateLocked(state) +
", write locked = " + isWriteLocked(state) +
", waits = " + waitCount(state) + "]";
}
@Override
public int sizeInBytes() {
return 8;
}
}