From 6c56813b5e428967f28f77d27e87e3270e78ca63 Mon Sep 17 00:00:00 2001 From: Peter Lawrey Date: Mon, 18 May 2015 10:12:34 +0100 Subject: [PATCH] HCOLL-333 Change for read and update, write and upgrade to come. --- .../chronicle/hash/impl/BigSegmentHeader.java | 61 +++++++++++++++++-- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/openhft/chronicle/hash/impl/BigSegmentHeader.java b/src/main/java/net/openhft/chronicle/hash/impl/BigSegmentHeader.java index e02488138..6261449b8 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/BigSegmentHeader.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/BigSegmentHeader.java @@ -56,8 +56,9 @@ public final class BigSegmentHeader implements SegmentHeader { static final long DELETED_OFFSET = EXCLUSIVE_LOCK_HOLDER_THREAD_ID_OFFSET + 8L; - private BigSegmentHeader() {} - + private BigSegmentHeader() { + } + @Override public long size(long address) { return UNSAFE.getInt(address + SIZE_OFFSET) & UNSIGNED_INT_MASK; @@ -232,7 +233,16 @@ public final class BigSegmentHeader implements SegmentHeader { } private boolean tryReadLock0(long address, long time, TimeUnit unit) { - long end = System.nanoTime() + unit.toNanos(time); + long timeInNanos = unit.toNanos(time); + if (timeInNanos < 2000000) { + return tryReadLockNanos(address, timeInNanos); + } else { + return tryReadLockMillis(address, (timeInNanos + 900000) / 1000000); + } + } + + private boolean tryReadLockNanos(long address, long timeInNanos) { + long end = System.nanoTime() + timeInNanos; do { if (tryReadLock(address)) return true; @@ -240,6 +250,23 @@ public final class BigSegmentHeader implements SegmentHeader { return false; } + /** + * Use a timer which is more insensitive to jumps in time like GCs and context switches. + */ + private boolean tryReadLockMillis(long address, long timeInMillis) { + long lastTime = System.currentTimeMillis(); + do { + if (tryReadLock(address)) + return true; + long now = System.currentTimeMillis(); + if (now != lastTime) { + lastTime = now; + timeInMillis--; + } + } while (timeInMillis >= 0); + return false; + } + @Override public boolean tryUpgradeReadToUpdateLock(long address) { int countWord = getCountWord(address); @@ -288,7 +315,16 @@ public final class BigSegmentHeader implements SegmentHeader { } private boolean tryUpdateLock0(long address, long time, TimeUnit unit) { - long end = System.nanoTime() + unit.toNanos(time); + long timeInNanos = unit.toNanos(time); + if (timeInNanos < 2000000) { + return tryUpdateLockNanos(address, timeInNanos); + } else { + return tryUpdateLockMillis(address, (timeInNanos + 900000) / 1000000); + } + } + + private boolean tryUpdateLockNanos(long address, long timeInNanos) { + long end = System.nanoTime() + timeInNanos; do { if (tryUpdateLock(address)) return true; @@ -296,6 +332,23 @@ public final class BigSegmentHeader implements SegmentHeader { return false; } + /** + * Use a timer which is more insensitive to jumps in time like GCs and context switches. + */ + private boolean tryUpdateLockMillis(long address, long timeInMillis) { + long lastTime = System.currentTimeMillis(); + do { + if (tryUpdateLock(address)) + return true; + long now = System.currentTimeMillis(); + if (now != lastTime) { + lastTime = now; + timeInMillis--; + } + } while (timeInMillis >= 0); + return false; + } + @Override public void writeLock(long address) { if (!tryWriteLock(address, 2, TimeUnit.SECONDS)) {