![JAR search and dependency download from the Maven repository](/logo.png)
org.objectfabric.MemoryView Maven / Gradle / Ivy
The newest version!
/**
* This file is part of ObjectFabric (http://objectfabric.org).
*
* ObjectFabric is licensed under the Apache License, Version 2.0, the terms
* of which may be found at http://www.apache.org/licenses/LICENSE-2.0.html.
*
* Copyright ObjectFabric Inc.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
package org.objectfabric;
final class MemoryView extends View {
private long[] _ticks;
private Buff[] _buffs;
MemoryView(Location location) {
super(location);
}
final void dispose() {
Object key;
if (Debug.THREADS) {
ThreadAssert.suspend(key = new Object());
ThreadAssert.resume(this, false);
}
for (int i = 0; _buffs != null && i < _buffs.length; i++)
if (_buffs[i] != null)
_buffs[i].recycle();
if (Debug.THREADS)
ThreadAssert.resume(key);
}
@Override
void getKnown(URI uri) {
long[] ticks;
synchronized (this) {
ticks = _ticks != null ? _ticks.clone() : null;
}
if (ticks == null && !location().isCache())
ticks = Tick.EMPTY;
if (ticks != null)
uri.onKnown(this, ticks);
}
@Override
void onKnown(URI uri, long[] ticks) {
boolean all = false;
long[] list = null;
int count = 0;
synchronized (this) {
if (_ticks == null || _ticks.length == 0)
all = true;
else {
for (int i = 0; i < ticks.length; i++) {
if (!Tick.isNull(ticks[i])) {
if (!Tick.contains(_ticks, ticks[i])) {
if (list == null)
list = new long[ticks.length];
list[count++] = ticks[i];
}
}
}
}
}
if (all) {
for (int i = 0; i < ticks.length; i++)
if (!Tick.isNull(ticks[i]))
uri.getBlock(this, ticks[i]);
} else if (list != null) {
for (int i = 0; i < count; i++)
uri.getBlock(this, list[i]);
}
}
@Override
void getBlock(URI uri, long tick) {
Buff duplicate = null;
synchronized (this) {
if (Debug.THREADS)
ThreadAssert.resume(this, false);
int index = Tick.indexOf(_ticks, tick);
if (index >= 0) {
Buff buff = _buffs[index];
if (buff != null) {
duplicate = buff.duplicate();
if (Debug.THREADS)
ThreadAssert.exchangeGive(duplicate, duplicate);
}
}
if (Debug.THREADS)
ThreadAssert.suspend(this);
}
if (duplicate != null) {
Buff[] duplicates = new Buff[] { duplicate };
if (Debug.THREADS) {
ThreadAssert.exchangeTake(duplicate);
ThreadAssert.exchangeGive(duplicates, duplicate);
}
uri.onBlock(this, tick, duplicates, null, true, null, false, null);
if (Debug.THREADS)
ThreadAssert.exchangeTake(duplicates);
duplicate.recycle();
}
}
@Override
void onBlock(URI uri, long tick, Buff[] buffs, long[] removals, boolean requested) {
int capacity = 0;
if (Debug.THREADS)
ThreadAssert.exchangeTake(buffs);
for (int i = 0; i < buffs.length; i++)
capacity += buffs[i].remaining();
Buff buff = Buff.createCustom(capacity, false);
if (Stats.ENABLED)
Stats.Instance.MemoryBlocksCreated.incrementAndGet();
for (int i = 0; i < buffs.length; i++) {
buff.putImmutably(buffs[i]);
if (Debug.THREADS)
ThreadAssert.exchangeGive(buffs, buffs[i]);
}
if (Debug.ENABLED)
Debug.assertion(buff.remaining() == 0);
buff.position(0);
buff.mark();
List recycle = null;
if (Debug.THREADS)
ThreadAssert.exchangeGive(buff, buff);
synchronized (this) {
if (Debug.THREADS) {
ThreadAssert.resume(this, false);
ThreadAssert.exchangeTake(buff);
}
int index = Tick.indexOf(_ticks, tick);
if (index < 0) {
index = add(tick);
_buffs[index] = buff;
if (Stats.ENABLED)
Stats.Instance.MemoryBlocksLive.incrementAndGet();
} else {
if (Debug.ENABLED)
Debug.assertion(_buffs[index] != null);
recycle = new List();
recycle.add(buff);
}
for (int i = 0; removals != null && i < removals.length; i++) {
if (!Tick.isNull(removals[i])) {
index = Tick.remove(_ticks, removals[i]);
if (index >= 0) {
if (recycle == null)
recycle = new List();
recycle.add(_buffs[index]);
_buffs[index] = null;
if (Stats.ENABLED)
Stats.Instance.MemoryBlocksLive.decrementAndGet();
}
}
}
if (Debug.THREADS) {
for (int i = 0; recycle != null && i < recycle.size(); i++)
ThreadAssert.exchangeGive(recycle, recycle.get(i));
ThreadAssert.suspend(this);
}
}
if (!location().isCache()) {
uri.onAck(this, tick);
if (Stats.ENABLED)
Stats.Instance.AckCreated.incrementAndGet();
}
if (recycle != null) {
if (Debug.THREADS)
ThreadAssert.exchangeTake(recycle);
for (int i = 0; i < recycle.size(); i++)
recycle.get(i).recycle();
}
}
private final int add(long tick) {
long[] ticks = _ticks;
Buff[] buffs = _buffs;
if (ticks == null || ticks.length == 0) {
ticks = new long[OpenMap.CAPACITY];
buffs = new Buff[OpenMap.CAPACITY];
} else if (Debug.THREADS)
Tick.checkSet(ticks);
int hash = Tick.hashTick(tick);
int index;
while ((index = Tick.tryToAdd(ticks, tick, hash)) < 0) {
long[] previousTicks = ticks;
Buff[] previousBuffs = buffs;
for (;;) {
ticks = new long[ticks.length << OpenMap.TIMES_TWO_SHIFT];
buffs = new Buff[buffs.length << OpenMap.TIMES_TWO_SHIFT];
if (rehash(previousTicks, ticks, previousBuffs, buffs))
break;
}
}
if (Debug.ENABLED)
Tick.checkSet(ticks);
_ticks = ticks;
_buffs = buffs;
return index;
}
private final boolean rehash(long[] previousTicks, long[] ticks, Buff[] previousBuffs, Buff[] buffs) {
for (int i = previousTicks.length - 1; i >= 0; i--) {
if (!Tick.isNull(previousTicks[i])) {
int index = Tick.tryToAdd(ticks, previousTicks[i], Tick.hashTick(previousTicks[i]));
if (index < 0)
return false;
buffs[index] = previousBuffs[i];
}
}
return true;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy