private boolean tryExpandTable() { if (tableResizing.get()) { throw new AssertionError("Expand requested in context of an existing resize - this should be impossible"); } else { tableResizing.set(Boolean.TRUE); try { Page newTablePage = expandTable(1); if (newTablePage == null) { return false; } else { freeTable(hashTablePage, hashtable, reprobeLimit()); hashTablePage = newTablePage; hashtable = newTablePage.asIntBuffer(); removedSlots = 0; return true; } } finally { tableResizing.remove(); } } }
private boolean tryExpandTable() { if (tableResizing.get()) { throw new AssertionError("Expand requested in context of an existing resize - this should be impossible"); } else { tableResizing.set(Boolean.TRUE); try { Page newTablePage = expandTable(1); if (newTablePage == null) { return false; } else { freeTable(hashTablePage, hashtable, reprobeLimit()); hashTablePage = newTablePage; hashtable = newTablePage.asIntBuffer(); removedSlots = 0; return true; } } finally { tableResizing.remove(); } } }
private void shrinkTableImpl() { if (tableResizing.get()) { LOGGER.debug("Shrink request ignored in the context of an in-process expand - likely self stealing"); } else { tableResizing.set(Boolean.TRUE); try { float shrinkRatio = (TABLE_RESIZE_THRESHOLD * getTableCapacity()) / size; int shrinkShift = Integer.numberOfTrailingZeros(Integer.highestOneBit(Math.max(2, (int) shrinkRatio))); Page newTablePage = shrinkTableImpl(shrinkShift); if (newTablePage == null) { currentTableShrinkThreshold = currentTableShrinkThreshold / 2; } else { currentTableShrinkThreshold = TABLE_SHRINK_THRESHOLD; freeTable(hashTablePage, hashtable, reprobeLimit()); hashTablePage = newTablePage; hashtable = newTablePage.asIntBuffer(); removedSlots = 0; } } finally { tableResizing.remove(); } } }
private void shrinkTableImpl() { if (tableResizing.get()) { LOGGER.debug("Shrink request ignored in the context of an in-process expand - likely self stealing"); } else { tableResizing.set(Boolean.TRUE); try { float shrinkRatio = (TABLE_RESIZE_THRESHOLD * getTableCapacity()) / size; int shrinkShift = Integer.numberOfTrailingZeros(Integer.highestOneBit(Math.max(2, (int) shrinkRatio))); Page newTablePage = shrinkTableImpl(shrinkShift); if (newTablePage == null) { currentTableShrinkThreshold = currentTableShrinkThreshold / 2; } else { currentTableShrinkThreshold = TABLE_SHRINK_THRESHOLD; freeTable(hashTablePage, hashtable, reprobeLimit()); hashTablePage = newTablePage; hashtable = newTablePage.asIntBuffer(); removedSlots = 0; } } finally { tableResizing.remove(); } } }
@Override public boolean updateEncoding(int hash, long oldEncoding, long newEncoding, long mask) { boolean updated = updateEncodingInTable(hashtable, reprobeLimit(), hash, oldEncoding, newEncoding, mask); if (hasUsedIterators) { pendingTableFrees.reap(); Iterator<PendingPage> it = pendingTableFrees.values(); while (it.hasNext()) { PendingPage pending = it.next(); updated |= updateEncodingInTable(pending.tablePage.asIntBuffer(), pending.reprobe, hash, oldEncoding, newEncoding, mask); } } return updated; }
@Override public boolean updateEncoding(int hash, long oldEncoding, long newEncoding, long mask) { boolean updated = updateEncodingInTable(hashtable, reprobeLimit(), hash, oldEncoding, newEncoding, mask); if (hasUsedIterators) { pendingTableFrees.reap(); Iterator<PendingPage> it = pendingTableFrees.values(); while (it.hasNext()) { PendingPage pending = it.next(); updated |= updateEncodingInTable(pending.tablePage.asIntBuffer(), pending.reprobe, hash, oldEncoding, newEncoding, mask); } } return updated; }
@FindbugsSuppressWarnings("ICAST_INTEGER_MULTIPLY_CAST_TO_LONG") protected OffHeapHashMap(PageSource source, boolean tableAllocationsSteal, StorageEngine<? super K, ? super V> storageEngine, int tableSize, boolean bootstrap) { if (storageEngine == null) { throw new NullPointerException("StorageEngine implementation must be non-null"); } this.storageEngine = storageEngine; this.tableSource = source; this.tableAllocationsSteal = tableAllocationsSteal; // Find a power of 2 >= initialCapacity int capacity = 1; while (capacity < tableSize) { capacity <<= 1; } this.initialTableSize = capacity; if (bootstrap) { this.hashTablePage = allocateTable(initialTableSize); if (hashTablePage == null) { String msg = "Initial table allocation failed.\n" + "Initial Table Size (slots) : " + initialTableSize + '\n' + "Allocation Will Require : " + DebuggingUtils.toBase2SuffixedString(initialTableSize * ENTRY_SIZE * (Integer.SIZE / Byte.SIZE)) + "B\n" + "Table Page Source : " + tableSource; throw new IllegalArgumentException(msg); } hashtable = hashTablePage.asIntBuffer(); } this.storageEngine.bind(this); }
@FindbugsSuppressWarnings("ICAST_INTEGER_MULTIPLY_CAST_TO_LONG") protected OffHeapHashMap(PageSource source, boolean tableAllocationsSteal, StorageEngine<? super K, ? super V> storageEngine, int tableSize, boolean bootstrap) { if (storageEngine == null) { throw new NullPointerException("StorageEngine implementation must be non-null"); } this.storageEngine = storageEngine; this.tableSource = source; this.tableAllocationsSteal = tableAllocationsSteal; // Find a power of 2 >= initialCapacity int capacity = 1; while (capacity < tableSize) { capacity <<= 1; } this.initialTableSize = capacity; if (bootstrap) { this.hashTablePage = allocateTable(initialTableSize); if (hashTablePage == null) { String msg = "Initial table allocation failed.\n" + "Initial Table Size (slots) : " + initialTableSize + '\n' + "Allocation Will Require : " + DebuggingUtils.toBase2SuffixedString(initialTableSize * ENTRY_SIZE * (Integer.SIZE / Byte.SIZE)) + "B\n" + "Table Page Source : " + tableSource; throw new IllegalArgumentException(msg); } hashtable = hashTablePage.asIntBuffer(); } this.storageEngine.bind(this); }
private void wipePendingTables() { if (hasUsedIterators) { pendingTableFrees.reap(); int[] zeros = new int[1024 >> 2]; Iterator<PendingPage> it = pendingTableFrees.values(); while (it.hasNext()) { PendingPage pending = it.next(); IntBuffer pendingTable = pending.tablePage.asIntBuffer(); pendingTable.clear(); while (pendingTable.hasRemaining()) { if (pendingTable.remaining() < zeros.length) { pendingTable.put(zeros, 0, pendingTable.remaining()); } else { pendingTable.put(zeros); } } pendingTable.clear(); } } }
hashtable = hashTablePage.asIntBuffer(); reprobeLimit = input.readInt();
private void wipePendingTables() { if (hasUsedIterators) { pendingTableFrees.reap(); int[] zeros = new int[1024 >> 2]; Iterator<PendingPage> it = pendingTableFrees.values(); while (it.hasNext()) { PendingPage pending = it.next(); IntBuffer pendingTable = pending.tablePage.asIntBuffer(); pendingTable.clear(); while (pendingTable.hasRemaining()) { if (pendingTable.remaining() < zeros.length) { pendingTable.put(zeros, 0, pendingTable.remaining()); } else { pendingTable.put(zeros); } } pendingTable.clear(); } } }
hashtable = hashTablePage.asIntBuffer(); reprobeLimit = input.readInt();
hashtable = hashTablePage.asIntBuffer(); reprobeLimit = input.readInt();
hashtable = hashTablePage.asIntBuffer(); reprobeLimit = input.readInt();
private void updatePendingTables(int hash, long oldEncoding, IntBuffer newEntry) { if (hasUsedIterators) { pendingTableFrees.reap(); Iterator<PendingPage> it = pendingTableFrees.values(); while (it.hasNext()) { PendingPage pending = it.next(); IntBuffer pendingTable = pending.tablePage.asIntBuffer(); pendingTable.position(indexFor(spread(hash), pendingTable)); for (int i = 0; i < pending.reprobe; i++) { if (!pendingTable.hasRemaining()) { pendingTable.rewind(); } IntBuffer entry = (IntBuffer) pendingTable.slice().limit(ENTRY_SIZE); if (isTerminating(entry)) { break; } else if (isPresent(entry) && (hash == entry.get(KEY_HASHCODE)) && (oldEncoding == readLong(entry, ENCODING))) { entry.put(newEntry.duplicate()); break; } else { pendingTable.position(pendingTable.position() + ENTRY_SIZE); } } } } }
private void updatePendingTables(int hash, long oldEncoding, IntBuffer newEntry) { if (hasUsedIterators) { pendingTableFrees.reap(); Iterator<PendingPage> it = pendingTableFrees.values(); while (it.hasNext()) { PendingPage pending = it.next(); IntBuffer pendingTable = pending.tablePage.asIntBuffer(); pendingTable.position(indexFor(spread(hash), pendingTable)); for (int i = 0; i < pending.reprobe; i++) { if (!pendingTable.hasRemaining()) { pendingTable.rewind(); } IntBuffer entry = (IntBuffer) pendingTable.slice().limit(ENTRY_SIZE); if (isTerminating(entry)) { break; } else if (isPresent(entry) && (hash == entry.get(KEY_HASHCODE)) && (oldEncoding == readLong(entry, ENCODING))) { entry.put(newEntry.duplicate()); break; } else { pendingTable.position(pendingTable.position() + ENTRY_SIZE); } } } } }
IntBuffer newTable = newTablePage.asIntBuffer();
private void allocateOrClearTable(int size) { int[] zeros = new int[1024 >> 2]; hashtable.clear(); while (hashtable.hasRemaining()) { if (hashtable.remaining() < zeros.length) { hashtable.put(zeros, 0, hashtable.remaining()); } else { hashtable.put(zeros); } } hashtable.clear(); wipePendingTables(); if (hashtable.capacity() > size * ENTRY_SIZE * ALLOCATE_ON_CLEAR_THRESHOLD_RATIO) { Page newTablePage = allocateTable(size); if (newTablePage != null) { freeTable(hashTablePage, hashtable, reprobeLimit()); hashTablePage = newTablePage; hashtable = newTablePage.asIntBuffer(); } } }
private void allocateOrClearTable(int size) { int[] zeros = new int[1024 >> 2]; hashtable.clear(); while (hashtable.hasRemaining()) { if (hashtable.remaining() < zeros.length) { hashtable.put(zeros, 0, hashtable.remaining()); } else { hashtable.put(zeros); } } hashtable.clear(); wipePendingTables(); if (hashtable.capacity() > size * ENTRY_SIZE * ALLOCATE_ON_CLEAR_THRESHOLD_RATIO) { Page newTablePage = allocateTable(size); if (newTablePage != null) { freeTable(hashTablePage, hashtable, reprobeLimit()); hashTablePage = newTablePage; hashtable = newTablePage.asIntBuffer(); } } }
IntBuffer newTable = newTablePage.asIntBuffer();