diff --git a/src/main/java/speiger/src/coreengine/NewInputTest.java b/src/main/java/speiger/src/coreengine/NewInputTest.java index 85e29df..45d1024 100644 --- a/src/main/java/speiger/src/coreengine/NewInputTest.java +++ b/src/main/java/speiger/src/coreengine/NewInputTest.java @@ -146,6 +146,7 @@ public class NewInputTest { // Font font = fonts.createFont(1F); TestModel model = new TestModel(builder.getBytes()); + builder.close(); // TestModel[] guiModel = new TestModel[1]; // List draws = new ObjectArrayList<>(); // TexturedBuffer buffer = new TexturedBuffer((K, V) -> { @@ -233,6 +234,7 @@ public class NewInputTest { builder.pos(-0.5F, -0.5F, 0).tex(0F, 1F).rgba(-1).endVertex(); TestModel model = new TestModel(builder.getBytes()); + builder.close(); while(!window.shouldClose()) { GLFW.glfwPollEvents(); if(window.changed()) { diff --git a/src/main/java/speiger/src/coreengine/NewRenderEngineTest.java b/src/main/java/speiger/src/coreengine/NewRenderEngineTest.java index 5087739..370cff3 100644 --- a/src/main/java/speiger/src/coreengine/NewRenderEngineTest.java +++ b/src/main/java/speiger/src/coreengine/NewRenderEngineTest.java @@ -68,7 +68,6 @@ public class NewRenderEngineTest { GraphicsDevice device = window.device(); int size = 512; int half = size >> 1; - int base = size >> 3; Drawable drawer = new Drawable(GLTextureFormat.RGBA, size, size); drawer.fill(0, 0, size, size, -1); drawer.fill(0, 0, half, half, 255, 0, 0, 255); @@ -97,6 +96,7 @@ public class NewRenderEngineTest { Mesh mesh = device.createMesh(Mesh.builder().layout(layout)); mesh.buffer(0, device.createBuffer(BufferType.ARRAY_BUFFER, BufferState.STATIC_DRAW).bind().set(builder.getBytes()).unbind()); + builder.close(); Sampler sampler = device.createSampler(SamplerSettings.builder().sampler(SampleMode.NEAREST).wrap(BorderMode.CLAMP_TO_EDGE).build()); VertexBuffer buffer = device.createBuffer(BufferType.UNIFORM_BUFFER, BufferState.STATIC_DRAW); diff --git a/src/main/java/speiger/src/coreengine/rendering/models/loader/ModelLoader.java b/src/main/java/speiger/src/coreengine/rendering/models/loader/ModelLoader.java index c0a47b2..55ff828 100644 --- a/src/main/java/speiger/src/coreengine/rendering/models/loader/ModelLoader.java +++ b/src/main/java/speiger/src/coreengine/rendering/models/loader/ModelLoader.java @@ -55,7 +55,7 @@ public class ModelLoader { if(line.startsWith("{")) { - if(currentName != null) + if(currentName != null && buffer != null) { resultModels.add(new SimpleModelData(currentName, null, buffer.array(), indexes)); currentName = null; @@ -70,7 +70,7 @@ public class ModelLoader buffer = ByteBuffer.allocate(Integer.parseInt(bounds[0]) * 28).order(ByteOrder.nativeOrder()); indexes = new int[Integer.parseInt(bounds[1])]; } - else if(line.startsWith("<")) + else if(line.startsWith("<") && buffer != null) { String[] data = line.substring(1, line.length() - 1).split(" "); String[] position = data[0].split(";"); @@ -79,7 +79,7 @@ public class ModelLoader ColorUtils.write(Integer.parseInt(data[1]), true, buffer); buffer.putFloat(Float.parseFloat(normal[0])).putFloat(Float.parseFloat(normal[1])).putFloat(Float.parseFloat(normal[2])); } - else if(line.startsWith("[")) + else if(line.startsWith("[") && indexes != null) { String[] data = line.substring(1, line.length() - 1).split(";"); for(int j = 0;j= size) throw new IllegalStateException("Out ouf Bounds"); - int arrayIndex = (index * bits) / 64; - int bitIndex = (index * bits) % 64; - data[arrayIndex] = data[arrayIndex] & ~(maxValue << bitIndex) | (value & maxValue) << bitIndex; - int left = 64 - bitIndex; - if(left < bits) { - int leftover = bits - left; - data[arrayIndex + 1] = data[arrayIndex + 1] >>> leftover << leftover | (value & maxValue) >> left; - } - } - - public void clear(int index) { - set(index, 0L); - } - - public long get(int index) { - if(index < 0 || index >= size) throw new IllegalStateException("Out ouf Bounds"); - int arrayIndex = (index * bits) / 64; - int bitIndex = (index * bits) % 64; - return (64 - bitIndex < bits ? (data[arrayIndex] >>> bitIndex | data[arrayIndex + 1] << (64 - bitIndex)) : (data[arrayIndex] >>> bitIndex)) & maxValue; - } - - public int getInt(int index) { - return (int)get(index); - } - - public int swapInt(int index, int newValue) { - int value = getInt(index); - if(newValue != value) set(index, newValue); - return value; - } - - public long swap(int index, long newValue) { - long value = get(index); - if(newValue != value) set(index, newValue); - return value; - } - - public int size() { - return size; - } - - public int bits() { - return bits; - } - - public long[] getData() { return data; } +package speiger.src.coreengine.utils.collections.collection; + +public class BitArray { + long[] data; + int size; + int bits; + long maxValue; + + public BitArray(int size, int bits) { + this.size = size; + this.bits = bits; + maxValue = (1L << bits) - 1L; + data = new long[arraySize(size * bits)]; + } + + public BitArray(int size, int bits, long[] data) { + this.size = size; + this.bits = bits; + maxValue = (1L << bits) - 1L; + int arraySize = arraySize(size * bits); + if(data == null || data.length != arraySize) { + this.data = new long[arraySize]; + if(this.data.length < arraySize) System.arraycopy(data, 0, this.data, 0, Math.min(this.data.length, arraySize)); + } + else this.data = data; + } + + private int arraySize(int entries) { + return entries % 64 == 0 ? entries / 64 : (entries / 64) + 1; + } + + public void set(int index, long value) { + if(index < 0 || index >= size) throw new IllegalStateException("Out ouf Bounds"); + int arrayIndex = (index * bits) / 64; + int bitIndex = (index * bits) % 64; + data[arrayIndex] = data[arrayIndex] & ~(maxValue << bitIndex) | (value & maxValue) << bitIndex; + int left = 64 - bitIndex; + if(left < bits) { + int leftover = bits - left; + data[arrayIndex + 1] = data[arrayIndex + 1] >>> leftover << leftover | (value & maxValue) >> left; + } + } + + public void clear(int index) { + set(index, 0L); + } + + public long get(int index) { + if(index < 0 || index >= size) throw new IllegalStateException("Out ouf Bounds"); + int arrayIndex = (index * bits) / 64; + int bitIndex = (index * bits) % 64; + return (64 - bitIndex < bits ? (data[arrayIndex] >>> bitIndex | data[arrayIndex + 1] << (64 - bitIndex)) : (data[arrayIndex] >>> bitIndex)) & maxValue; + } + + public int getInt(int index) { + return (int)get(index); + } + + public int swapInt(int index, int newValue) { + int value = getInt(index); + if(newValue != value) set(index, newValue); + return value; + } + + public long swap(int index, long newValue) { + long value = get(index); + if(newValue != value) set(index, newValue); + return value; + } + + public int size() { + return size; + } + + public int bits() { + return bits; + } + + public long[] getData() { return data; } } \ No newline at end of file diff --git a/src/main/java/speiger/src/coreengine/utils/collections/managers/dynamic/DynamicDataManager.java b/src/main/java/speiger/src/coreengine/utils/collections/managers/dynamic/DynamicDataManager.java index a790236..58616ce 100644 --- a/src/main/java/speiger/src/coreengine/utils/collections/managers/dynamic/DynamicDataManager.java +++ b/src/main/java/speiger/src/coreengine/utils/collections/managers/dynamic/DynamicDataManager.java @@ -1,215 +1,215 @@ -package speiger.src.coreengine.utils.collections.managers.dynamic; - -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import speiger.src.collections.ints.collections.IntIterator; -import speiger.src.collections.ints.maps.abstracts.AbstractInt2IntMap.BasicEntry; -import speiger.src.collections.ints.maps.interfaces.Int2IntMap; -import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap; -import speiger.src.collections.ints.misc.pairs.IntObjectPair; -import speiger.src.collections.ints.sets.IntAVLTreeSet; -import speiger.src.collections.ints.sets.IntSet; -import speiger.src.collections.objects.lists.ObjectArrayList; -import speiger.src.collections.objects.sets.ObjectAVLTreeSet; -import speiger.src.collections.objects.utils.ObjectLists; -import speiger.src.coreengine.utils.collections.pools.ThreadPool; - -public class DynamicDataManager -{ - static final ThreadPool SLOTS = new ThreadPool<>(1000, DataSlot::new, DataSlot::clear); - final IDynamicDataHandler manager; - Int2ObjectMap slots = Int2ObjectMap.builder().linkedMap(); - Set emptySlots = new ObjectAVLTreeSet<>(); - IntSet changedSlots = new IntAVLTreeSet(); - DataSlot lastSlot = null; - - public DynamicDataManager(IDynamicDataHandler manager) - { - this.manager = manager; - } - - public boolean add(int dataIndex, T value) - { - if(slots.containsKey(dataIndex)) return false; - return add(dataIndex, manager.toBytes(value)); - } - - protected boolean add(int dataIndex, byte[] data) - { - if(!emptySlots.isEmpty()) - { - for(Iterator iter = emptySlots.iterator();iter.hasNext();) - { - DataSlot slot = iter.next(); - if(slot.getFreeBytes() >= data.length) - { - slot.setData(dataIndex, data); - slots.put(dataIndex, slot); - changedSlots.add(dataIndex); - return true; - } - } - } - DataSlot next = SLOTS.get(); - next.set(lastSlot, dataIndex, data); - slots.put(dataIndex, next); - changedSlots.add(dataIndex); - lastSlot = next; - return true; - } - - public boolean contains(int dataIndex) - { - return slots.containsKey(dataIndex); - } - - public boolean update(int dataIndex, T value) - { - DataSlot slot = slots.get(dataIndex); - if(slot != null) - { - byte[] data = manager.toBytes(value); - if(slot.getFreeBytes() >= data.length) - { - slot.setData(dataIndex, data); - changedSlots.add(dataIndex); - return true; - } - else - { - slot.setData(-1, null); - slots.remove(dataIndex); - add(dataIndex, data); - emptySlots.add(slot); - return true; - } - } - return false; - } - - public Iterator iterator(int byteOffset) - { - return new Iterator() { - BasicEntry entry = new BasicEntry(); - DataSlot current = findNextSlot(lastSlot); - @Override - public boolean hasNext() - { - return current != null; - } - - DataSlot findNextSlot(DataSlot input) - { - for(input = input.previous; input != null && input.value == null;input = input.previous); - return input; - } - - @Override - public Int2IntMap.Entry next() - { - if(!hasNext()) throw new IllegalStateException(); - entry.set(current.dataIndex, current.byteOffset / byteOffset); - current = findNextSlot(current); - return entry; - } - }; - } - - public boolean remove(int dataIndex) - { - DataSlot slot = slots.remove(dataIndex); - if(slot != null) - { - slot.setData(-1, null); - emptySlots.add(slot); - return true; - } - return false; - } - - protected void clearEmptySlots() - { - while(lastSlot != null && lastSlot.value == null) - { - DataSlot prev = lastSlot; - emptySlots.remove(prev); - lastSlot = prev.previous; - SLOTS.accept(prev); - } - } - - public void clear() - { - slots.clear(); - emptySlots.clear(); - changedSlots.clear(); - while(lastSlot != null) - { - DataSlot prev = lastSlot; - lastSlot = prev.previous; - SLOTS.accept(prev); - } - } - - public void update() - { - int last = getEndSize(); - clearEmptySlots(); - if(changedSlots.isEmpty()) - { - if(last != getEndSize()) - { - manager.uploadBytes(ObjectLists.empty(), getEndSize()); - } - return; - } - List> list = new ObjectArrayList<>(); - while(!changedSlots.isEmpty()) - { - DataSlot start = null; - DataSlot current = null; - int bytesAllocated = 0; - for(IntIterator iter = changedSlots.iterator();iter.hasNext();) - { - DataSlot slot = slots.get(iter.nextInt()); - iter.remove(); - if(slot == null) break; - if(current == null || current.next == slot) - { - current = slot; - if(start == null) start = slot; - bytesAllocated += slot.getUsedBytes(); - continue; - } - break; - } - if(bytesAllocated <= 0) continue; - byte[] data = new byte[bytesAllocated]; - int byteOffset = start.byteOffset; - bytesAllocated = 0; - while(start.byteOffset <= current.byteOffset); - { - System.arraycopy(start.value, 0, data, bytesAllocated, start.value.length); - bytesAllocated += start.getUsedBytes(); - start = start.next; - } - list.add(IntObjectPair.of(byteOffset, data)); - } - if(!list.isEmpty()) - { - manager.uploadBytes(list, getEndSize()); - } - } - - private int getEndSize() - { - return lastSlot == null ? 0 : lastSlot.getNextByteOffset(); - } - - public int size() - { - return slots.size(); - } -} +package speiger.src.coreengine.utils.collections.managers.dynamic; + +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import speiger.src.collections.ints.collections.IntIterator; +import speiger.src.collections.ints.maps.abstracts.AbstractInt2IntMap.BasicEntry; +import speiger.src.collections.ints.maps.interfaces.Int2IntMap; +import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap; +import speiger.src.collections.ints.misc.pairs.IntObjectPair; +import speiger.src.collections.ints.sets.IntAVLTreeSet; +import speiger.src.collections.ints.sets.IntSet; +import speiger.src.collections.objects.lists.ObjectArrayList; +import speiger.src.collections.objects.sets.ObjectAVLTreeSet; +import speiger.src.collections.objects.utils.ObjectLists; +import speiger.src.coreengine.utils.collections.pools.ThreadPool; + +public class DynamicDataManager +{ + static final ThreadPool SLOTS = new ThreadPool<>(1000, DataSlot::new, DataSlot::clear); + final IDynamicDataHandler manager; + Int2ObjectMap slots = Int2ObjectMap.builder().linkedMap(); + Set emptySlots = new ObjectAVLTreeSet<>(); + IntSet changedSlots = new IntAVLTreeSet(); + DataSlot lastSlot = null; + + public DynamicDataManager(IDynamicDataHandler manager) + { + this.manager = manager; + } + + public boolean add(int dataIndex, T value) + { + if(slots.containsKey(dataIndex)) return false; + return add(dataIndex, manager.toBytes(value)); + } + + protected boolean add(int dataIndex, byte[] data) + { + if(!emptySlots.isEmpty()) + { + for(Iterator iter = emptySlots.iterator();iter.hasNext();) + { + DataSlot slot = iter.next(); + if(slot.getFreeBytes() >= data.length) + { + slot.setData(dataIndex, data); + slots.put(dataIndex, slot); + changedSlots.add(dataIndex); + return true; + } + } + } + DataSlot next = SLOTS.get(); + next.set(lastSlot, dataIndex, data); + slots.put(dataIndex, next); + changedSlots.add(dataIndex); + lastSlot = next; + return true; + } + + public boolean contains(int dataIndex) + { + return slots.containsKey(dataIndex); + } + + public boolean update(int dataIndex, T value) + { + DataSlot slot = slots.get(dataIndex); + if(slot != null) + { + byte[] data = manager.toBytes(value); + if(slot.getFreeBytes() >= data.length) + { + slot.setData(dataIndex, data); + changedSlots.add(dataIndex); + return true; + } + else + { + slot.setData(-1, null); + slots.remove(dataIndex); + add(dataIndex, data); + emptySlots.add(slot); + return true; + } + } + return false; + } + + public Iterator iterator(int byteOffset) + { + return new Iterator() { + BasicEntry entry = new BasicEntry(); + DataSlot current = findNextSlot(lastSlot); + @Override + public boolean hasNext() + { + return current != null; + } + + DataSlot findNextSlot(DataSlot input) + { + for(input = input.previous; input != null && input.value == null;input = input.previous); + return input; + } + + @Override + public Int2IntMap.Entry next() + { + if(!hasNext()) throw new IllegalStateException(); + entry.set(current.dataIndex, current.byteOffset / byteOffset); + current = findNextSlot(current); + return entry; + } + }; + } + + public boolean remove(int dataIndex) + { + DataSlot slot = slots.remove(dataIndex); + if(slot != null) + { + slot.setData(-1, null); + emptySlots.add(slot); + return true; + } + return false; + } + + protected void clearEmptySlots() + { + while(lastSlot != null && lastSlot.value == null) + { + DataSlot prev = lastSlot; + emptySlots.remove(prev); + lastSlot = prev.previous; + SLOTS.accept(prev); + } + } + + public void clear() + { + slots.clear(); + emptySlots.clear(); + changedSlots.clear(); + while(lastSlot != null) + { + DataSlot prev = lastSlot; + lastSlot = prev.previous; + SLOTS.accept(prev); + } + } + + public void update() + { + int last = getEndSize(); + clearEmptySlots(); + if(changedSlots.isEmpty()) + { + if(last != getEndSize()) + { + manager.uploadBytes(ObjectLists.empty(), getEndSize()); + } + return; + } + List> list = new ObjectArrayList<>(); + while(!changedSlots.isEmpty()) + { + DataSlot start = null; + DataSlot current = null; + int bytesAllocated = 0; + for(IntIterator iter = changedSlots.iterator();iter.hasNext();) + { + DataSlot slot = slots.get(iter.nextInt()); + iter.remove(); + if(slot == null) break; + if(current == null || current.next == slot) + { + current = slot; + if(start == null) start = slot; + bytesAllocated += slot.getUsedBytes(); + continue; + } + break; + } + if(bytesAllocated <= 0 || start == null || current == null) continue; + byte[] data = new byte[bytesAllocated]; + int byteOffset = start.byteOffset; + bytesAllocated = 0; + while(start.byteOffset <= current.byteOffset); + { + System.arraycopy(start.value, 0, data, bytesAllocated, start.value.length); + bytesAllocated += start.getUsedBytes(); + start = start.next; + } + list.add(IntObjectPair.of(byteOffset, data)); + } + if(!list.isEmpty()) + { + manager.uploadBytes(list, getEndSize()); + } + } + + private int getEndSize() + { + return lastSlot == null ? 0 : lastSlot.getNextByteOffset(); + } + + public int size() + { + return slots.size(); + } +} diff --git a/src/main/java/speiger/src/coreengine/utils/collections/managers/fixed/FixedDataManager.java b/src/main/java/speiger/src/coreengine/utils/collections/managers/fixed/FixedDataManager.java index fdbf2a7..4ca494f 100644 --- a/src/main/java/speiger/src/coreengine/utils/collections/managers/fixed/FixedDataManager.java +++ b/src/main/java/speiger/src/coreengine/utils/collections/managers/fixed/FixedDataManager.java @@ -1,357 +1,357 @@ -package speiger.src.coreengine.utils.collections.managers.fixed; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.List; -import java.util.concurrent.Callable; - -import speiger.src.collections.ints.collections.IntCollection; -import speiger.src.collections.ints.collections.IntIterator; -import speiger.src.collections.ints.functions.IntComparator; -import speiger.src.collections.ints.lists.IntArrayList; -import speiger.src.collections.ints.lists.IntList; -import speiger.src.collections.ints.maps.impl.hash.Int2IntOpenHashMap; -import speiger.src.collections.ints.maps.interfaces.Int2IntMap; -import speiger.src.collections.ints.misc.pairs.IntObjectPair; -import speiger.src.collections.ints.sets.IntAVLTreeSet; -import speiger.src.collections.ints.sets.IntLinkedOpenHashSet; -import speiger.src.collections.ints.sets.IntSet; -import speiger.src.collections.ints.sets.IntSortedSet; -import speiger.src.collections.objects.lists.ObjectArrayList; -import speiger.src.collections.objects.utils.ObjectArrays; -import speiger.src.collections.objects.utils.ObjectLists; -import speiger.src.coreengine.utils.collections.pools.ThreadPool; - -public class FixedDataManager -{ - static final ThreadPool SLOTS = new ThreadPool<>(1000, FixedSlot::new); - - final int bytesPerEntry; - final IFixedDataHandler manager; - Int2IntMap slots = new Int2IntOpenHashMap(); - IntArrayList slotData = new IntArrayList(); - IntSortedSet freeSlots = new IntAVLTreeSet(); - IntSet changes = new IntLinkedOpenHashSet(); - - public FixedDataManager(int bytesPerEntry, IFixedDataHandler manager) - { - this.bytesPerEntry = bytesPerEntry; - this.manager = manager; - slots.setDefaultReturnValue(-1); - } - - public boolean add(int dataIndex) - { - if(dataIndex == -1) - { - throw new IllegalStateException("-1 isnt allowed to be a dataIndex"); - } - if(slots.containsKey(dataIndex)) - { - return false; - } - if(freeSlots.isEmpty()) - { - slots.put(dataIndex, slotData.size()); - slotData.add(dataIndex); - changes.add(dataIndex); - return true; - } - int slot = freeSlots.pollFirstInt(); - slots.put(dataIndex, slot); - slotData.set(slot, dataIndex); - changes.add(dataIndex); - return true; - } - - public void addAll(IntCollection indexes) - { - for(int index : indexes) - { - add(index); - } - } - - public boolean contains(int dataIndex) - { - return slots.containsKey(dataIndex); - } - - public boolean update(int dataIndex) - { - if(slots.containsKey(dataIndex)) - { - changes.add(dataIndex); - return true; - } - return false; - } - - public void updateAll(IntCollection indexes) - { - for(int index : indexes) - { - if(slots.containsKey(index)) - { - changes.add(index); - } - } - } - - public boolean remove(int dataIndex) - { - int slot = slots.remove(dataIndex); - if(slot >= 0 && slot < slotData.size()) - { - slotData.set(slot, -1); - freeSlots.add(slot); - changes.remove(dataIndex); - return true; - } - return false; - } - - public void removeAll(IntCollection indexes) - { - for(int index : indexes) - { - remove(index); - } - } - - public void clear() - { - changes.clear(); - slots.clear(); - freeSlots.clear(); - slotData.clear(); - } - - public void reload(boolean now) - { - if(slots.isEmpty()) - { - return; - } - changes.addAll(slots.keySet()); - if(now) - { - updateNow(); - } - } - - public int size() - { - return slots.size(); - } - - public IntIterator valueIterator() - { - return slotData.iterator(); - } - - public void copy(FixedDataManager manager) - { - IntList list = manager.slotData; - for(int i = 0,m=list.size();i call = update(); - if(call != null) - { - call.call().run(); - } - } - catch(Exception e){} - } - - public Callable update() - { - int lastSize = slotData.size(); - clearEmptySlots(); - if(changes.isEmpty()) - { - if(slotData.size() != lastSize) - { - return new ShrinkTask(new FinishingTask(manager, ObjectLists.empty(), size())); - } - return null; - } - FixedSlot[] slots = SLOTS.get(new FixedSlot[changes.size()]); - int index = 0; - for(int dataIndex : changes) - { - slots[index++].set(dataIndex, this.slots.get(dataIndex)); - } - changes.clear(); - return new ProcessTask(slots, size(), bytesPerEntry, manager); - } - - protected void clearEmptySlots() - { - if(freeSlots.isEmpty()) - { - return; - } - if(slots.isEmpty()) - { - freeSlots.clear(); - slotData.clear(); - changes.clear(); - return; - } - int size = freeSlots.size(); - while(size > 0) - { - size -= ensureData(); - if(slotData.isEmpty() || freeSlots.isEmpty()) - { - break; - } - int index = freeSlots.pollFirstInt(); - int dataIndex = slotData.pop(); - slotData.set(index, dataIndex); - slots.put(dataIndex, index); - changes.add(dataIndex); - } - } - - protected int ensureData() - { - int cleared = 0; - while(slotData.top() == -1) - { - freeSlots.remove(slotData.size() - 1); - slotData.pop(); - cleared++; - } - return cleared; - } - - static class ProcessTask implements Callable - { - FixedSlot[] slots; - int size; - int bytes; - IFixedDataHandler handler; - - public ProcessTask(FixedSlot[] slots, int size, int bytes, IFixedDataHandler handler) - { - this.slots = slots; - this.size = size; - this.bytes = bytes; - this.handler = handler; - } - - @Override - public Runnable call() - { - ObjectArrays.quickSort(slots); - List fixed = new ObjectArrayList(); - List> data = new ObjectArrayList<>(); - FixedSlot first = null; - FixedSlot last = null; - for(int i = 0,m=slots.length;i - { - Runnable run; - - public ShrinkTask(Runnable run) - { - this.run = run; - } - - @Override - public Runnable call() throws Exception - { - return run; - } - } - - static class FinishingTask implements Runnable - { - IFixedDataHandler handler; - List> data; - int size; - - public FinishingTask(IFixedDataHandler handler, List> data, int size) - { - this.handler = handler; - this.data = data; - this.size = size; - } - - @Override - public void run() - { - handler.updateData(data, size); - } - } -} +package speiger.src.coreengine.utils.collections.managers.fixed; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.List; +import java.util.concurrent.Callable; + +import speiger.src.collections.ints.collections.IntCollection; +import speiger.src.collections.ints.collections.IntIterator; +import speiger.src.collections.ints.functions.IntComparator; +import speiger.src.collections.ints.lists.IntArrayList; +import speiger.src.collections.ints.lists.IntList; +import speiger.src.collections.ints.maps.impl.hash.Int2IntOpenHashMap; +import speiger.src.collections.ints.maps.interfaces.Int2IntMap; +import speiger.src.collections.ints.misc.pairs.IntObjectPair; +import speiger.src.collections.ints.sets.IntAVLTreeSet; +import speiger.src.collections.ints.sets.IntLinkedOpenHashSet; +import speiger.src.collections.ints.sets.IntSet; +import speiger.src.collections.ints.sets.IntSortedSet; +import speiger.src.collections.objects.lists.ObjectArrayList; +import speiger.src.collections.objects.utils.ObjectArrays; +import speiger.src.collections.objects.utils.ObjectLists; +import speiger.src.coreengine.utils.collections.pools.ThreadPool; + +public class FixedDataManager +{ + static final ThreadPool SLOTS = new ThreadPool<>(1000, FixedSlot::new); + + final int bytesPerEntry; + final IFixedDataHandler manager; + Int2IntMap slots = new Int2IntOpenHashMap(); + IntArrayList slotData = new IntArrayList(); + IntSortedSet freeSlots = new IntAVLTreeSet(); + IntSet changes = new IntLinkedOpenHashSet(); + + public FixedDataManager(int bytesPerEntry, IFixedDataHandler manager) + { + this.bytesPerEntry = bytesPerEntry; + this.manager = manager; + slots.setDefaultReturnValue(-1); + } + + public boolean add(int dataIndex) + { + if(dataIndex == -1) + { + throw new IllegalStateException("-1 isnt allowed to be a dataIndex"); + } + if(slots.containsKey(dataIndex)) + { + return false; + } + if(freeSlots.isEmpty()) + { + slots.put(dataIndex, slotData.size()); + slotData.add(dataIndex); + changes.add(dataIndex); + return true; + } + int slot = freeSlots.pollFirstInt(); + slots.put(dataIndex, slot); + slotData.set(slot, dataIndex); + changes.add(dataIndex); + return true; + } + + public void addAll(IntCollection indexes) + { + for(int index : indexes) + { + add(index); + } + } + + public boolean contains(int dataIndex) + { + return slots.containsKey(dataIndex); + } + + public boolean update(int dataIndex) + { + if(slots.containsKey(dataIndex)) + { + changes.add(dataIndex); + return true; + } + return false; + } + + public void updateAll(IntCollection indexes) + { + for(int index : indexes) + { + if(slots.containsKey(index)) + { + changes.add(index); + } + } + } + + public boolean remove(int dataIndex) + { + int slot = slots.remove(dataIndex); + if(slot >= 0 && slot < slotData.size()) + { + slotData.set(slot, -1); + freeSlots.add(slot); + changes.remove(dataIndex); + return true; + } + return false; + } + + public void removeAll(IntCollection indexes) + { + for(int index : indexes) + { + remove(index); + } + } + + public void clear() + { + changes.clear(); + slots.clear(); + freeSlots.clear(); + slotData.clear(); + } + + public void reload(boolean now) + { + if(slots.isEmpty()) + { + return; + } + changes.addAll(slots.keySet()); + if(now) + { + updateNow(); + } + } + + public int size() + { + return slots.size(); + } + + public IntIterator valueIterator() + { + return slotData.iterator(); + } + + public void copy(FixedDataManager manager) + { + IntList list = manager.slotData; + for(int i = 0,m=list.size();i call = update(); + if(call != null) + { + call.call().run(); + } + } + catch(Exception e){} + } + + public Callable update() + { + int lastSize = slotData.size(); + clearEmptySlots(); + if(changes.isEmpty()) + { + if(slotData.size() != lastSize) + { + return new ShrinkTask(new FinishingTask(manager, ObjectLists.empty(), size())); + } + return null; + } + FixedSlot[] slots = SLOTS.get(new FixedSlot[changes.size()]); + int index = 0; + for(int dataIndex : changes) + { + slots[index++].set(dataIndex, this.slots.get(dataIndex)); + } + changes.clear(); + return new ProcessTask(slots, size(), bytesPerEntry, manager); + } + + protected void clearEmptySlots() + { + if(freeSlots.isEmpty()) + { + return; + } + if(slots.isEmpty()) + { + freeSlots.clear(); + slotData.clear(); + changes.clear(); + return; + } + int size = freeSlots.size(); + while(size > 0) + { + size -= ensureData(); + if(slotData.isEmpty() || freeSlots.isEmpty()) + { + break; + } + int index = freeSlots.pollFirstInt(); + int dataIndex = slotData.pop(); + slotData.set(index, dataIndex); + slots.put(dataIndex, index); + changes.add(dataIndex); + } + } + + protected int ensureData() + { + int cleared = 0; + while(slotData.top() == -1) + { + freeSlots.remove(slotData.size() - 1); + slotData.pop(); + cleared++; + } + return cleared; + } + + static class ProcessTask implements Callable + { + FixedSlot[] slots; + int size; + int bytes; + IFixedDataHandler handler; + + public ProcessTask(FixedSlot[] slots, int size, int bytes, IFixedDataHandler handler) + { + this.slots = slots; + this.size = size; + this.bytes = bytes; + this.handler = handler; + } + + @Override + public Runnable call() + { + ObjectArrays.quickSort(slots); + List fixed = new ObjectArrayList(); + List> data = new ObjectArrayList<>(); + FixedSlot first = null; + FixedSlot last = null; + for(int i = 0,m=slots.length;i + { + Runnable run; + + public ShrinkTask(Runnable run) + { + this.run = run; + } + + @Override + public Runnable call() throws Exception + { + return run; + } + } + + static class FinishingTask implements Runnable + { + IFixedDataHandler handler; + List> data; + int size; + + public FinishingTask(IFixedDataHandler handler, List> data, int size) + { + this.handler = handler; + this.data = data; + this.size = size; + } + + @Override + public void run() + { + handler.updateData(data, size); + } + } +}