org.apache.rocketmq.shaded.io.opentelemetry.sdk.metrics.internal.export.CollectionHandle Maven / Gradle / Ivy
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package org.apache.rocketmq.shaded.io.opentelemetry.sdk.metrics.internal.export;
import java.util.AbstractSet;
import java.util.BitSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
import javax.annotation.Nullable;
/**
* A handle for a collection-pipeline of metrics.
*
* This class provides an efficient means of leasing and tracking exporters.
*
*
This class is internal and is hence not for public use. Its APIs are unstable and can change
* at any time.
*/
public final class CollectionHandle {
/** The index of this handle. */
private final int index;
private CollectionHandle(int index) {
this.index = index;
}
/** Construct a new (efficient) mutable set for tracking collection handles. */
public static Set mutableSet() {
return new CollectionHandleSet();
}
/**
* Construct a new (mutable) set consisting of the passed in collection handles.
*
* Used by tests.
*/
static Set of(CollectionHandle... handles) {
Set result = mutableSet();
for (CollectionHandle handle : handles) {
result.add(handle);
}
return result;
}
/**
* Construct a new supplier of collection handles.
*
* Handles returned by this supplier should not be used with unique handles produced by any
* other supplier.
*/
public static Supplier createSupplier() {
return new Supplier() {
private final AtomicInteger nextIndex = new AtomicInteger(1);
@Override
public CollectionHandle get() {
return new CollectionHandle(nextIndex.getAndIncrement());
}
};
}
@Override
public int hashCode() {
return index;
}
@Override
public boolean equals(@Nullable Object other) {
if (this == other) {
return true;
}
if (other == null) {
return false;
}
if (!(other instanceof CollectionHandle)) {
return false;
}
return index == ((CollectionHandle) other).index;
}
@Override
public String toString() {
return "CollectionHandle(" + index + ")";
}
/** An optimised bitset version of {@code Set}. */
private static class CollectionHandleSet extends AbstractSet {
private final BitSet storage = new BitSet();
@Override
public Iterator iterator() {
return new MyIterator();
}
@Override
public boolean add(CollectionHandle handle) {
if (storage.get(handle.index)) {
return false;
}
storage.set(handle.index);
return true;
}
@Override
public boolean contains(Object handle) {
if (handle instanceof CollectionHandle) {
return storage.get(((CollectionHandle) handle).index);
}
return false;
}
@Override
public boolean containsAll(Collection other) {
if (other instanceof CollectionHandleSet) {
BitSet result = (BitSet) storage.clone();
BitSet otherStorage = ((CollectionHandleSet) other).storage;
result.and(otherStorage);
return result.equals(otherStorage);
}
return super.containsAll(other);
}
private class MyIterator implements Iterator {
private int currentIndex = 0;
@Override
public boolean hasNext() {
return (currentIndex != -1) && storage.nextSetBit(currentIndex) != -1;
}
@Override
public CollectionHandle next() {
int result = storage.nextSetBit(currentIndex);
if (result != -1) {
// Start checking next bit next time.
currentIndex = result + 1;
return new CollectionHandle(result);
}
throw new NoSuchElementException("Called `.next` on iterator with no remaining values.");
}
}
@Override
public int size() {
return storage.cardinality();
}
}
}