public void put(K key, V value) {
long hashCode = hashCode(key);
long currentPtr = bucketFor(hashCode);
int newSize = sizeOf(value);
RWLock lock = lockFor(hashCode).lockWrite();
try {
for (long entry; (entry = unsafe.getAddress(currentPtr)) != 0; currentPtr = entry + NEXT_OFFSET) {
if (unsafe.getLong(entry + HASH_OFFSET) == hashCode && equalsAt(entry, key)) {
int oldSize = sizeOf(entry);
if (newSize <= oldSize) {
setTimeAt(entry);
setValueAt(entry, value);
return;
}
unsafe.putAddress(currentPtr, unsafe.getAddress(entry + NEXT_OFFSET));
destroyEntry(entry);
count.decrementAndGet();
break;
}
}
long entry = allocateEntry(key, hashCode, newSize);
unsafe.putLong(entry + HASH_OFFSET, hashCode);
unsafe.putAddress(entry + NEXT_OFFSET, unsafe.getAddress(currentPtr));
setTimeAt(entry);
setValueAt(entry, value);
unsafe.putAddress(currentPtr, entry);
count.incrementAndGet();
} finally {
lock.unlockWrite();
}
}