net.openhft.chronicle.wire.domestic.reduction.Reductions Maven / Gradle / Ivy
/*
* Copyright 2016-2022 chronicle.software
*
* https://chronicle.software
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.openhft.chronicle.wire.domestic.reduction;
import net.openhft.chronicle.wire.SelfDescribingMarshallable;
import net.openhft.chronicle.wire.Wire;
import net.openhft.chronicle.wire.domestic.extractor.ToDoubleDocumentExtractor;
import net.openhft.chronicle.wire.domestic.extractor.ToLongDocumentExtractor;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
import java.util.concurrent.atomic.DoubleAccumulator;
import java.util.concurrent.atomic.LongAccumulator;
import java.util.concurrent.atomic.LongAdder;
import java.util.function.DoubleBinaryOperator;
import java.util.function.DoubleSupplier;
import java.util.function.LongBinaryOperator;
import java.util.function.LongSupplier;
import static net.openhft.chronicle.core.util.ObjectUtils.requireNonNull;
/**
* This is the Reductions utility class.
* It provides static methods to create various types of Reductions, offering functionalities
* related to longs, doubles, and counting excerpts.
*/
public final class Reductions {
// Suppresses default constructor, ensuring non-instantiability.
private Reductions() {
}
// Specialized Reductions
/**
* Creates and returns a new Reduction that will extract elements of type {@code long} using
* the provided {@code extractor} and will accumulate values using the provided {@code accumulator}.
* The initial state of the reduction will be the provided {@code identity}.
*
* The returned Reduction is guaranteed to not create any internal objects.
*
* @param extractor to apply on each document (non-null)
* @param identity initial start value
* @param accumulator to apply for each element (non-null)
* @return a new Reduction reducing long values
* @throws NullPointerException if any objects provided are {@code null}.
*/
public static Reduction reducingLong(@NotNull final ToLongDocumentExtractor extractor,
final long identity,
@NotNull final LongBinaryOperator accumulator) {
requireNonNull(extractor);
requireNonNull(accumulator);
return Reduction.ofLong(extractor)
.reducing(
() -> new LongAccumulator(accumulator, identity),
LongAccumulator::accumulate,
LongAccumulator::get
);
}
/**
* Creates and returns a new Reduction that will extract elements of type {@code double} using
* the provided {@code extractor} and will accumulate values using the provided {@code accumulator}.
* The initial state of the reduction will be the provided {@code identity}.
*
* The returned Reduction is guaranteed to not create any internal objects.
*
* @param extractor to apply on each document (non-null)
* @param identity initial start value
* @param accumulator to apply for each element (non-null)
* @return a new Reduction reducing double values
* @throws NullPointerException if any objects provided are {@code null}.
*/
public static Reduction reducingDouble(@NotNull final ToDoubleDocumentExtractor extractor,
final double identity,
@NotNull final DoubleBinaryOperator accumulator) {
requireNonNull(extractor);
requireNonNull(accumulator);
return Reduction.ofDouble(extractor)
.reducing(
() -> new DoubleAccumulator(accumulator, identity),
DoubleAccumulator::accumulate,
DoubleAccumulator::get
);
}
/**
* Creates and returns a new Reduction that will count the number of excerpts.
*
* The returned Reduction is guaranteed to not create any internal objects.
*
* @return a new Reduction counting excerpts
*/
public static Reduction counting() {
return Reduction.ofLong(
(wire, index) -> 1L)
.reducing(
LongAdder::new,
LongAdder::add,
LongAdder::sum
);
}
/**
* A Reduction class that counts the number of excerpts that have been processed.
*
* This is an example of a public class with configurable properties that can be
* referenced in a YAML configuration file.
*/
public static final class Counting extends SelfDescribingMarshallable implements Reduction {
// An atomic field updater to provide thread-safe updates to the counter
private static final AtomicLongFieldUpdater UPDATER =
AtomicLongFieldUpdater.newUpdater(Counting.class, "counter");
// A volatile counter to ensure atomic read/write operations across multiple threads
private volatile long counter;
@Override
public void onExcerpt(@NotNull Wire wire, long index) {
UPDATER.getAndIncrement(this);
}
@NotNull
@Override
public LongSupplier reduction() {
return () -> counter;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final Counting that = (Counting) o;
return this.counter == that.counter;
}
@Override
public int hashCode() {
return Long.hashCode(counter);
}
}
}