org.terracotta.offheapstore.AbstractLockedOffHeapHashMap Maven / Gradle / Ivy
Show all versions of offheap-store Show documentation
/*
* Copyright 2015 Terracotta, Inc., a Software AG company.
*
* 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 org.terracotta.offheapstore;
import java.nio.ByteBuffer;
import java.util.AbstractSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.function.BiFunction;
import java.util.function.Function;
import org.terracotta.offheapstore.paging.PageSource;
import org.terracotta.offheapstore.storage.StorageEngine;
/**
* An abstract locked off-heap map.
*
* Subclasses must implement the {@code readLock()} and {@code writeLock()}
* methods such that they return the correct locks under which read and write
* operations must occur.
*
* @param the type of keys maintained by this map
* @param the type of mapped values
*
* @author Chris Dennis
*/
public abstract class AbstractLockedOffHeapHashMap extends OffHeapHashMap implements Segment {
public AbstractLockedOffHeapHashMap(PageSource source, StorageEngine super K, ? super V> storageEngine) {
super(source, storageEngine);
}
public AbstractLockedOffHeapHashMap(PageSource source, boolean tableAllocationsSteal, StorageEngine super K, ? super V> storageEngine) {
super(source, tableAllocationsSteal, storageEngine);
}
public AbstractLockedOffHeapHashMap(PageSource source, StorageEngine super K, ? super V> storageEngine, boolean bootstrap) {
super(source, storageEngine, bootstrap);
}
public AbstractLockedOffHeapHashMap(PageSource source, StorageEngine super K, ? super V> storageEngine, int tableSize) {
super(source, storageEngine, tableSize);
}
public AbstractLockedOffHeapHashMap(PageSource source, boolean tableAllocationsSteal, StorageEngine super K, ? super V> storageEngine, int tableSize) {
super(source, tableAllocationsSteal, storageEngine, tableSize);
}
public AbstractLockedOffHeapHashMap(PageSource source, StorageEngine super K, ? super V> storageEngine, int tableSize, boolean bootstrap) {
super(source, false, storageEngine, tableSize, bootstrap);
}
@Override
public int size() {
Lock l = readLock();
l.lock();
try {
return super.size();
} finally {
l.unlock();
}
}
@Override
public boolean containsKey(Object key) {
Lock l = readLock();
l.lock();
try {
return super.containsKey(key);
} finally {
l.unlock();
}
}
@Override
public V get(Object key) {
Lock l = readLock();
l.lock();
try {
return super.get(key);
} finally {
l.unlock();
}
}
@Override
public Long getEncodingForHashAndBinary(int hash, ByteBuffer binaryKey) {
Lock l = readLock();
l.lock();
try {
return super.getEncodingForHashAndBinary(hash, binaryKey);
} finally {
l.unlock();
}
}
@Override
public long installMappingForHashAndEncoding(int pojoHash, ByteBuffer offheapBinaryKey, ByteBuffer offheapBinaryValue, int metadata) {
Lock l = writeLock();
l.lock();
try {
return super.installMappingForHashAndEncoding(pojoHash, offheapBinaryKey, offheapBinaryValue, metadata);
} finally {
l.unlock();
}
}
@Override
public V put(K key, V value) {
Lock l = writeLock();
l.lock();
try {
return super.put(key, value);
} finally {
l.unlock();
}
}
@Override
public V put(K key, V value, int metadata) {
Lock l = writeLock();
l.lock();
try {
return super.put(key, value, metadata);
} finally {
l.unlock();
}
}
@Override
public V fill(K key, V value) {
Lock l = writeLock();
l.lock();
try {
return super.fill(key, value);
} finally {
l.unlock();
}
}
@Override
public V fill(K key, V value, int metadata) {
Lock l = writeLock();
l.lock();
try {
return super.fill(key, value, metadata);
} finally {
l.unlock();
}
}
@Override
public V remove(Object key) {
Lock l = writeLock();
l.lock();
try {
return super.remove(key);
} finally {
l.unlock();
}
}
@Override
public boolean removeNoReturn(Object key) {
Lock l = writeLock();
l.lock();
try {
return super.removeNoReturn(key);
} finally {
l.unlock();
}
}
@Override
public void clear() {
Lock l = writeLock();
l.lock();
try {
super.clear();
} finally {
l.unlock();
}
}
@Override
public V putIfAbsent(K key, V value) {
Lock l = writeLock();
l.lock();
try {
if (key == null || value == null) {
throw new NullPointerException();
}
V existing = get(key);
if (existing == null) {
put(key, value);
}
return existing;
} finally {
l.unlock();
}
}
@Override
public boolean remove(Object key, Object value) {
Lock l = writeLock();
l.lock();
try {
if (key == null) {
throw new NullPointerException();
}
if (value == null) {
return false;
}
V existing = get(key);
if (value.equals(existing)) {
remove(key);
return true;
} else {
return false;
}
} finally {
l.unlock();
}
}
@Override
public boolean replace(K key, V oldValue, V newValue) {
Lock l = writeLock();
l.lock();
try {
V existing = get(key);
if (oldValue.equals(existing)) {
put(key, newValue);
return true;
} else {
return false;
}
} finally {
l.unlock();
}
}
@Override
public V replace(K key, V value) {
Lock l = writeLock();
l.lock();
try {
if (value == null || key == null) {
throw new NullPointerException();
}
V existing = get(key);
if (existing != null) {
put(key, value);
}
return existing;
} finally {
l.unlock();
}
}
@Override
public Integer getMetadata(Object key, int mask) {
Lock l = readLock();
l.lock();
try {
return super.getMetadata(key, mask);
} finally {
l.unlock();
}
}
@Override
public Integer getAndSetMetadata(Object key, int mask, int values) {
Lock l = writeLock();
l.lock();
try {
return super.getAndSetMetadata(key, mask, values);
} finally {
l.unlock();
}
}
@Override
public V getValueAndSetMetadata(Object key, int mask, int values) {
Lock l = writeLock();
l.lock();
try {
return super.getValueAndSetMetadata(key, mask, values);
} finally {
l.unlock();
}
}
/*
* remove used by EntrySet
*/
@Override
protected boolean removeMapping(Object o) {
Lock l = writeLock();
l.lock();
try {
return super.removeMapping(o);
} finally {
l.unlock();
}
}
@Override
public boolean evict(int index, boolean shrink) {
Lock l = writeLock();
l.lock();
try {
return super.evict(index, shrink);
} finally {
l.unlock();
}
}
@Override
protected Set> createEntrySet() {
return new LockedEntrySet();
}
protected class LockedEntrySet extends AbstractSet> {
@Override
public Iterator> iterator() {
Lock l = readLock();
l.lock();
try {
return new LockedEntryIterator();
} finally {
l.unlock();
}
}
@Override
public boolean contains(Object o) {
if (!(o instanceof Entry, ?>)) {
return false;
}
@SuppressWarnings("unchecked")
Entry e = (Entry) o;
Lock l = readLock();
l.lock();
try {
V value = AbstractLockedOffHeapHashMap.this.get(e.getKey());
return value != null && value.equals(e.getValue());
} finally {
l.unlock();
}
}
@Override
public boolean remove(Object o) {
return AbstractLockedOffHeapHashMap.this.removeMapping(o);
}
@Override
public int size() {
return AbstractLockedOffHeapHashMap.this.size();
}
@Override
public void clear() {
AbstractLockedOffHeapHashMap.this.clear();
}
}
protected class LockedEntryIterator extends EntryIterator {
@Override
public Entry next() {
Lock l = readLock();
l.lock();
try {
return super.next();
} finally {
l.unlock();
}
}
@Override
public void remove() {
Lock l = writeLock();
l.lock();
try {
super.remove();
} finally {
l.unlock();
}
}
@Override
protected void checkForConcurrentModification() {
//no-op
}
}
@Override
protected Set createKeySet() {
return new LockedKeySet();
}
protected class LockedKeySet extends AbstractSet {
@Override
public Iterator iterator() {
Lock l = readLock();
l.lock();
try {
return new LockedKeyIterator();
} finally {
l.unlock();
}
}
@Override
public boolean contains(Object o) {
return AbstractLockedOffHeapHashMap.this.containsKey(o);
}
@Override
public boolean remove(Object o) {
return AbstractLockedOffHeapHashMap.this.remove(o) != null;
}
@Override
public int size() {
return AbstractLockedOffHeapHashMap.this.size();
}
@Override
public void clear() {
AbstractLockedOffHeapHashMap.this.clear();
}
}
protected class LockedKeyIterator extends KeyIterator {
@Override
public K next() {
Lock l = readLock();
l.lock();
try {
return super.next();
} finally {
l.unlock();
}
}
@Override
public void remove() {
Lock l = writeLock();
l.lock();
try {
super.remove();
} finally {
l.unlock();
}
}
@Override
protected void checkForConcurrentModification() {
//no-op
}
}
@Override
public void destroy() {
Lock l = writeLock();
l.lock();
try {
super.destroy();
} finally {
l.unlock();
}
}
@Override
public boolean shrink() {
Lock l = writeLock();
l.lock();
try {
return storageEngine.shrink();
} finally {
l.unlock();
}
}
@Override
public abstract Lock readLock();
@Override
public abstract Lock writeLock();
/*
* JDK-8-alike metadata methods
*/
@Override
public MetadataTuple computeWithMetadata(K key, BiFunction super K, ? super MetadataTuple, ? extends MetadataTuple> remappingFunction) {
Lock l = writeLock();
l.lock();
try {
return super.computeWithMetadata(key, remappingFunction);
} finally {
l.unlock();
}
}
@Override
public MetadataTuple computeIfAbsentWithMetadata(K key, Function super K,? extends MetadataTuple> mappingFunction) {
Lock l = writeLock();
l.lock();
try {
return super.computeIfAbsentWithMetadata(key, mappingFunction);
} finally {
l.unlock();
}
}
@Override
public MetadataTuple computeIfPresentWithMetadata(K key, BiFunction super K,? super MetadataTuple,? extends MetadataTuple> remappingFunction) {
Lock l = writeLock();
l.lock();
try {
return super.computeIfPresentWithMetadata(key, remappingFunction);
} finally {
l.unlock();
}
}
@Override
public Map removeAllWithHash(int hash) {
Lock l = writeLock();
l.lock();
try {
return super.removeAllWithHash(hash);
} finally {
l.unlock();
}
}
}