private void shiftLowestInactiveHalfBucketContentsLeft(final int shiftAmount, final int preShiftZeroIndex) { final int numberOfBinaryOrdersOfMagnitude = shiftAmount >> subBucketHalfCountMagnitude; // The lowest inactive half-bucket (not including the 0 value) is special: unlike all other half // buckets, the lowest half bucket values cannot be scaled by simply changing the // normalizing offset. Instead, they must be individually re-recorded at the new // scale, and cleared from the current one. // // We know that all half buckets "below" the current lowest one are full of 0s, because // we would have overflowed otherwise. So we need to shift the values in the current // lowest half bucket into that range (including the current lowest half bucket itself). // Iterating up from the lowermost non-zero "from slot" and copying values to the newly // scaled "to slot" (and then zeroing the "from slot"), will work in a single pass, // because the scale "to slot" index will always be a lower index than its or any // preceding non-scaled "from slot" index: // // (Note that we specifically avoid slot 0, as it is directly handled in the outer case) for (int fromIndex = 1; fromIndex < subBucketHalfCount; fromIndex++) { long toValue = valueFromIndex(fromIndex) << numberOfBinaryOrdersOfMagnitude; int toIndex = countsArrayIndex(toValue); int normalizedToIndex = normalizeIndex(toIndex, inactiveCounts.getNormalizingIndexOffset(), inactiveCounts.length()); long countAtFromIndex = inactiveCounts.get(fromIndex + preShiftZeroIndex); inactiveCounts.lazySet(normalizedToIndex, countAtFromIndex); inactiveCounts.lazySet(fromIndex + preShiftZeroIndex, 0); } // Note that the above loop only creates O(N) work for histograms that have values in // the lowest half-bucket (excluding the 0 value). Histograms that never have values // there (e.g. all integer value histograms used as internal storage in DoubleHistograms) // will never loop, and their shifts will remain O(1). }
private void copyInactiveCountsContentsOnResize( AtomicLongArrayWithNormalizingOffset oldInactiveCounts, int countsDelta) { int oldNormalizedZeroIndex = normalizeIndex(0, oldInactiveCounts.getNormalizingIndexOffset(), oldInactiveCounts.length()); // Copy old inactive contents to (current) newly sized inactiveCounts: for (int i = 0; i < oldInactiveCounts.length(); i++) { inactiveCounts.lazySet(i, oldInactiveCounts.get(i)); } if (oldNormalizedZeroIndex != 0) { // We need to shift the stuff from the zero index and up to the end of the array: int newNormalizedZeroIndex = oldNormalizedZeroIndex + countsDelta; int lengthToCopy = (inactiveCounts.length() - countsDelta) - oldNormalizedZeroIndex; int src, dst; for (src = oldNormalizedZeroIndex, dst = newNormalizedZeroIndex; src < oldNormalizedZeroIndex + lengthToCopy; src++, dst++) { inactiveCounts.lazySet(dst, oldInactiveCounts.get(src)); } for (dst = oldNormalizedZeroIndex; dst < newNormalizedZeroIndex; dst++) { inactiveCounts.lazySet(dst, 0); } } }
@Override void recordConvertedDoubleValue(final double value) { long criticalValue = wrp.writerCriticalSectionEnter(); try { long integerValue = (long) (value * activeCounts.doubleToIntegerValueConversionRatio); int index = countsArrayIndex(integerValue); activeCounts.incrementAndGet( normalizeIndex(index, activeCounts.getNormalizingIndexOffset(), activeCounts.length())); updateMinAndMax(integerValue); incrementTotalCount(); } finally { wrp.writerCriticalSectionExit(criticalValue); } }
@Override long getCountAtIndex(final int index) { try { wrp.readerLock(); assert (countsArrayLength == activeCounts.length()); assert (countsArrayLength == inactiveCounts.length()); long activeCount = activeCounts.get( normalizeIndex(index, activeCounts.getNormalizingIndexOffset(), activeCounts.length())); long inactiveCount = inactiveCounts.get( normalizeIndex(index, inactiveCounts.getNormalizingIndexOffset(), inactiveCounts.length())); return activeCount + inactiveCount; } finally { wrp.readerUnlock(); } }
@Override public void recordConvertedDoubleValueWithCount(final double value, final long count) throws ArrayIndexOutOfBoundsException { long criticalValue = wrp.writerCriticalSectionEnter(); try { long integerValue = (long) (value * activeCounts.doubleToIntegerValueConversionRatio); int index = countsArrayIndex(integerValue); activeCounts.addAndGet( normalizeIndex(index, activeCounts.getNormalizingIndexOffset(), activeCounts.length()), count); updateMinAndMax(integerValue); addToTotalCount(count); } finally { wrp.writerCriticalSectionExit(criticalValue); } }
@Override void setCountAtIndex(final int index, final long value) { try { wrp.readerLock(); assert (countsArrayLength == activeCounts.length()); assert (countsArrayLength == inactiveCounts.length()); activeCounts.lazySet( normalizeIndex(index, activeCounts.getNormalizingIndexOffset(), activeCounts.length()), value); inactiveCounts.lazySet( normalizeIndex(index, inactiveCounts.getNormalizingIndexOffset(), inactiveCounts.length()), 0); } finally { wrp.readerUnlock(); } }
@Override int getNormalizingIndexOffset() { return activeCounts.getNormalizingIndexOffset(); }
@Override void addToCountAtIndex(final int index, final long value) { long criticalValue = wrp.writerCriticalSectionEnter(); try { activeCounts.addAndGet( normalizeIndex(index, activeCounts.getNormalizingIndexOffset(), activeCounts.length()), value); } finally { wrp.writerCriticalSectionExit(criticalValue); } }
@Override void incrementCountAtIndex(final int index) { long criticalValue = wrp.writerCriticalSectionEnter(); try { activeCounts.incrementAndGet( normalizeIndex(index, activeCounts.getNormalizingIndexOffset(), activeCounts.length())); } finally { wrp.writerCriticalSectionExit(criticalValue); } }
new AtomicLongArrayWithNormalizingOffset( newArrayLength, inactiveCounts.getNormalizingIndexOffset() ); AtomicLongArrayWithNormalizingOffset newInactiveCounts2 = new AtomicLongArrayWithNormalizingOffset( newArrayLength, activeCounts.getNormalizingIndexOffset() );
assert (countsArrayLength == inactiveCounts.length()); assert (activeCounts.getNormalizingIndexOffset() == inactiveCounts.getNormalizingIndexOffset()); if (normalizingIndexOffset == activeCounts.getNormalizingIndexOffset()) { return; // Nothing to do. int zeroIndex = normalizeIndex(0, inactiveCounts.getNormalizingIndexOffset(), inactiveCounts.length()); long inactiveZeroValueCount = inactiveCounts.get(zeroIndex); inactiveCounts.lazySet(zeroIndex, 0); zeroIndex = normalizeIndex(0, inactiveCounts.getNormalizingIndexOffset(), inactiveCounts.length()); inactiveCounts.lazySet(zeroIndex, inactiveZeroValueCount); zeroIndex = normalizeIndex(0, inactiveCounts.getNormalizingIndexOffset(), inactiveCounts.length()); inactiveZeroValueCount = inactiveCounts.get(zeroIndex); inactiveCounts.lazySet(zeroIndex, 0); zeroIndex = normalizeIndex(0, inactiveCounts.getNormalizingIndexOffset(), inactiveCounts.length()); inactiveCounts.lazySet(zeroIndex, inactiveZeroValueCount);
private void shiftLowestInactiveHalfBucketContentsLeft(final int shiftAmount, final int preShiftZeroIndex) { final int numberOfBinaryOrdersOfMagnitude = shiftAmount >> subBucketHalfCountMagnitude; // The lowest inactive half-bucket (not including the 0 value) is special: unlike all other half // buckets, the lowest half bucket values cannot be scaled by simply changing the // normalizing offset. Instead, they must be individually re-recorded at the new // scale, and cleared from the current one. // // We know that all half buckets "below" the current lowest one are full of 0s, because // we would have overflowed otherwise. So we need to shift the values in the current // lowest half bucket into that range (including the current lowest half bucket itself). // Iterating up from the lowermost non-zero "from slot" and copying values to the newly // scaled "to slot" (and then zeroing the "from slot"), will work in a single pass, // because the scale "to slot" index will always be a lower index than its or any // preceding non-scaled "from slot" index: // // (Note that we specifically avoid slot 0, as it is directly handled in the outer case) for (int fromIndex = 1; fromIndex < subBucketHalfCount; fromIndex++) { long toValue = valueFromIndex(fromIndex) << numberOfBinaryOrdersOfMagnitude; int toIndex = countsArrayIndex(toValue); int normalizedToIndex = normalizeIndex(toIndex, inactiveCounts.getNormalizingIndexOffset(), inactiveCounts.length()); long countAtFromIndex = inactiveCounts.get(fromIndex + preShiftZeroIndex); inactiveCounts.lazySet(normalizedToIndex, countAtFromIndex); inactiveCounts.lazySet(fromIndex + preShiftZeroIndex, 0); } // Note that the above loop only creates O(N) work for histograms that have values in // the lowest half-bucket (excluding the 0 value). Histograms that never have values // there (e.g. all integer value histograms used as internal storage in DoubleHistograms) // will never loop, and their shifts will remain O(1). }
private void copyInactiveCountsContentsOnResize( AtomicLongArrayWithNormalizingOffset oldInactiveCounts, int countsDelta) { int oldNormalizedZeroIndex = normalizeIndex(0, oldInactiveCounts.getNormalizingIndexOffset(), oldInactiveCounts.length()); // Copy old inactive contents to (current) newly sized inactiveCounts: for (int i = 0; i < oldInactiveCounts.length(); i++) { inactiveCounts.lazySet(i, oldInactiveCounts.get(i)); } if (oldNormalizedZeroIndex != 0) { // We need to shift the stuff from the zero index and up to the end of the array: int newNormalizedZeroIndex = oldNormalizedZeroIndex + countsDelta; int lengthToCopy = (inactiveCounts.length() - countsDelta) - oldNormalizedZeroIndex; int src, dst; for (src = oldNormalizedZeroIndex, dst = newNormalizedZeroIndex; src < oldNormalizedZeroIndex + lengthToCopy; src++, dst++) { inactiveCounts.lazySet(dst, oldInactiveCounts.get(src)); } for (dst = oldNormalizedZeroIndex; dst < newNormalizedZeroIndex; dst++) { inactiveCounts.lazySet(dst, 0); } } }
@Override long getCountAtIndex(final int index) { try { wrp.readerLock(); assert (countsArrayLength == activeCounts.length()); assert (countsArrayLength == inactiveCounts.length()); long activeCount = activeCounts.get( normalizeIndex(index, activeCounts.getNormalizingIndexOffset(), activeCounts.length())); long inactiveCount = inactiveCounts.get( normalizeIndex(index, inactiveCounts.getNormalizingIndexOffset(), inactiveCounts.length())); return activeCount + inactiveCount; } finally { wrp.readerUnlock(); } }
@Override void setCountAtIndex(final int index, final long value) { try { wrp.readerLock(); assert (countsArrayLength == activeCounts.length()); assert (countsArrayLength == inactiveCounts.length()); activeCounts.lazySet( normalizeIndex(index, activeCounts.getNormalizingIndexOffset(), activeCounts.length()), value); inactiveCounts.lazySet( normalizeIndex(index, inactiveCounts.getNormalizingIndexOffset(), inactiveCounts.length()), 0); } finally { wrp.readerUnlock(); } }
@Override void recordConvertedDoubleValue(final double value) { long criticalValue = wrp.writerCriticalSectionEnter(); try { long integerValue = (long) (value * activeCounts.doubleToIntegerValueConversionRatio); int index = countsArrayIndex(integerValue); activeCounts.incrementAndGet( normalizeIndex(index, activeCounts.getNormalizingIndexOffset(), activeCounts.length())); updateMinAndMax(integerValue); incrementTotalCount(); } finally { wrp.writerCriticalSectionExit(criticalValue); } }
@Override int getNormalizingIndexOffset() { return activeCounts.getNormalizingIndexOffset(); }
@Override public void recordConvertedDoubleValueWithCount(final double value, final long count) throws ArrayIndexOutOfBoundsException { long criticalValue = wrp.writerCriticalSectionEnter(); try { long integerValue = (long) (value * activeCounts.doubleToIntegerValueConversionRatio); int index = countsArrayIndex(integerValue); activeCounts.addAndGet( normalizeIndex(index, activeCounts.getNormalizingIndexOffset(), activeCounts.length()), count); updateMinAndMax(integerValue); addToTotalCount(count); } finally { wrp.writerCriticalSectionExit(criticalValue); } }
@Override void addToCountAtIndex(final int index, final long value) { long criticalValue = wrp.writerCriticalSectionEnter(); try { activeCounts.addAndGet( normalizeIndex(index, activeCounts.getNormalizingIndexOffset(), activeCounts.length()), value); } finally { wrp.writerCriticalSectionExit(criticalValue); } }
@Override void incrementCountAtIndex(final int index) { long criticalValue = wrp.writerCriticalSectionEnter(); try { activeCounts.incrementAndGet( normalizeIndex(index, activeCounts.getNormalizingIndexOffset(), activeCounts.length())); } finally { wrp.writerCriticalSectionExit(criticalValue); } }