
com.tangosol.util.AbstractSafeLongArray Maven / Gradle / Ivy
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
package com.tangosol.util;
import com.oracle.coherence.common.util.AutoLock.Sentry;
/**
* An abstract base class for thread-safe {@link LongArray}s which are protected by lock(s).
*
* @author mf 2014.10.01
*/
public abstract class AbstractSafeLongArray
implements LongArray
{
@Override
public V get(long lIndex)
{
try (Sentry> sentry = acquireReadLock())
{
return sentry.getResource().get(lIndex);
}
}
@Override
public long floorIndex(long lIndex)
{
try (Sentry> sentry = acquireReadLock())
{
return sentry.getResource().floorIndex(lIndex);
}
}
@Override
public V floor(long lIndex)
{
try (Sentry> sentry = acquireReadLock())
{
return sentry.getResource().floor(lIndex);
}
}
@Override
public long ceilingIndex(long lIndex)
{
try (Sentry> sentry = acquireReadLock())
{
return sentry.getResource().ceilingIndex(lIndex);
}
}
@Override
public V ceiling(long lIndex)
{
try (Sentry> sentry = acquireReadLock())
{
return sentry.getResource().ceiling(lIndex);
}
}
@Override
public V set(long lIndex, V oValue)
{
try (Sentry> sentry = acquireWriteLock())
{
return sentry.getResource().set(lIndex, oValue);
}
}
@Override
public long add(V oValue)
{
try (Sentry> sentry = acquireWriteLock())
{
return sentry.getResource().add(oValue);
}
}
@Override
public boolean exists(long lIndex)
{
try (Sentry> sentry = acquireReadLock())
{
return sentry.getResource().exists(lIndex);
}
}
@Override
public V remove(long lIndex)
{
try (Sentry> sentry = acquireWriteLock())
{
return sentry.getResource().remove(lIndex);
}
}
@Override
public void remove(long lIndexFrom, long lIndexTo)
{
try (Sentry> sentry = acquireWriteLock())
{
sentry.getResource().remove(lIndexFrom, lIndexTo);
}
}
@Override
public boolean contains(V oValue)
{
try (Sentry> sentry = acquireReadLock())
{
return sentry.getResource().contains(oValue);
}
}
@Override
public void clear()
{
try (Sentry> sentry = acquireWriteLock())
{
sentry.getResource().clear();
}
}
@Override
public boolean isEmpty()
{
try (Sentry> sentry = acquireReadLock())
{
return sentry.getResource().isEmpty();
}
}
@Override
public int getSize()
{
try (Sentry> sentry = acquireReadLock())
{
return sentry.getResource().getSize();
}
}
@Override
public long getFirstIndex()
{
try (Sentry> sentry = acquireReadLock())
{
return sentry.getResource().getFirstIndex();
}
}
@Override
public long getLastIndex()
{
try (Sentry> sentry = acquireReadLock())
{
return sentry.getResource().getLastIndex();
}
}
@Override
public long indexOf(V oValue)
{
try (Sentry> sentry = acquireReadLock())
{
return sentry.getResource().indexOf(oValue);
}
}
@Override
public long indexOf(V oValue, long lIndex)
{
try (Sentry> sentry = acquireReadLock())
{
return sentry.getResource().indexOf(oValue, lIndex);
}
}
@Override
public long lastIndexOf(V oValue)
{
try (Sentry> sentry = acquireReadLock())
{
return sentry.getResource().lastIndexOf(oValue);
}
}
@Override
public long lastIndexOf(V oValue, long lIndex)
{
try (Sentry> sentry = acquireReadLock())
{
return sentry.getResource().lastIndexOf(oValue, lIndex);
}
}
@Override
public Iterator iterator()
{
return instantiateSafeIterator(/*fForward*/ true, Long.MIN_VALUE);
}
@Override
public Iterator iterator(long lIndex)
{
return instantiateSafeIterator(/*fForward*/ true, lIndex);
}
@Override
public Iterator reverseIterator()
{
return instantiateSafeIterator(/*fForward*/ false, Long.MAX_VALUE);
}
@Override
public Iterator reverseIterator(long lIndex)
{
return instantiateSafeIterator(/*fForward*/ false, lIndex);
}
// ----- Object interface -----------------------------------------------
@Override
public String toString()
{
try (Sentry> sentry = acquireReadLock())
{
return sentry.getResource().toString();
}
}
@Override
abstract public AbstractSafeLongArray clone();
// ----- AbstractSafeLongArray ------------------------------------------
/**
* Acquire the read lock.
*
* @return the lock sentry
*/
protected abstract Sentry> acquireReadLock();
/**
* Acquire the write lock.
*
* @return the lock sentry
*/
protected abstract Sentry> acquireWriteLock();
// ----- inner class: SafeIterator -------------------------------------
/**
* Instantiate a SafeIterator around the specified delegate iterator.
*
* @param fForward true if a forward iterator is to be returned
* @param lIndexFrom the start index
*
* @return the safe iterator
*/
protected SafeIterator instantiateSafeIterator(boolean fForward, long lIndexFrom)
{
try (Sentry> sentry = acquireReadLock())
{
return new SafeIterator(sentry.getResource(), fForward, lIndexFrom);
}
}
/**
* A lock based LongArray Iterator. Note the implementation is thread-safe so long as
* the wrapped unsafe LongArray supports stable iteration when accessed from a single thread.
* Specifically that performing an add or remove operation directly against the LongArray
* while being iterated does not corrupt the state of either the LongArray or the Iterator.
*
* An alternate approach would be to maintain a write counter and to refresh the delegate iterator
* each time the write counter changes, the refresh would be cheap as it could use iterator(m_lastIndex).
*/
protected class SafeIterator
implements Iterator
{
protected SafeIterator(LongArray delegate, boolean fForward, long lIndexFrom)
{
f_delegate = fForward
? lIndexFrom == Long.MIN_VALUE
? delegate.iterator()
: delegate.iterator(lIndexFrom)
: lIndexFrom == Long.MAX_VALUE
? delegate.reverseIterator()
: delegate.reverseIterator(lIndexFrom);
}
@Override
public boolean hasNext()
{
try (Sentry sentry = acquireReadLock())
{
return f_delegate.hasNext();
}
}
@Override
public V next()
{
V value;
long lIndex;
try (Sentry sentry = acquireReadLock())
{
value = f_delegate.next();
lIndex = f_delegate.getIndex();
}
m_valueLast = value;
m_lIndexLast = lIndex;
return value;
}
@Override
public long getIndex()
{
// no need to take lock, use cached index
ensureValid();
return m_lIndexLast;
}
@Override
public V getValue()
{
// no need to take lock, use cached value
ensureValid();
return (V) m_valueLast;
}
@Override
public V setValue(V oValue)
{
try (Sentry sentry = acquireWriteLock())
{
V value = f_delegate.setValue(oValue);
m_valueLast = oValue;
return value;
}
}
@Override
public void remove()
{
try (Sentry sentry = acquireWriteLock())
{
f_delegate.remove();
}
m_valueLast = NO_VALUE;
}
/**
* Ensure that the cached value/index are valid.
*/
protected void ensureValid()
{
if (m_valueLast == NO_VALUE)
{
throw new IllegalStateException("missing call to next()");
}
}
/**
* The delegate iterator.
*/
protected final Iterator f_delegate;
/**
* The last value returned from the iterator.
*/
protected Object m_valueLast = NO_VALUE;
/**
* The index associated with the last returned value
*/
protected long m_lIndexLast;
}
/**
* A value guaranteed to never be in the array.
*/
protected static final Object NO_VALUE = new Object();
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy