388 lines
13 KiB
Java
388 lines
13 KiB
Java
|
package com.google.common.util.concurrent;
|
||
|
|
||
|
import com.google.common.base.MoreObjects;
|
||
|
import com.google.common.base.Preconditions;
|
||
|
import com.google.common.base.Supplier;
|
||
|
import com.google.common.collect.ImmutableList;
|
||
|
import com.google.common.collect.Iterables;
|
||
|
import com.google.common.collect.MapMaker;
|
||
|
import com.google.common.math.IntMath;
|
||
|
import java.lang.ref.Reference;
|
||
|
import java.lang.ref.ReferenceQueue;
|
||
|
import java.lang.ref.WeakReference;
|
||
|
import java.math.RoundingMode;
|
||
|
import java.util.Arrays;
|
||
|
import java.util.Collections;
|
||
|
import java.util.concurrent.ConcurrentMap;
|
||
|
import java.util.concurrent.Semaphore;
|
||
|
import java.util.concurrent.atomic.AtomicReferenceArray;
|
||
|
import java.util.concurrent.locks.Condition;
|
||
|
import java.util.concurrent.locks.Lock;
|
||
|
import java.util.concurrent.locks.ReadWriteLock;
|
||
|
import java.util.concurrent.locks.ReentrantLock;
|
||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||
|
|
||
|
/* loaded from: classes2.dex */
|
||
|
public abstract class Striped<L> {
|
||
|
private static final int ALL_SET = -1;
|
||
|
private static final int LARGE_LAZY_CUTOFF = 1024;
|
||
|
private static final Supplier<ReadWriteLock> READ_WRITE_LOCK_SUPPLIER = new Supplier<ReadWriteLock>() { // from class: com.google.common.util.concurrent.Striped.5
|
||
|
@Override // com.google.common.base.Supplier
|
||
|
public ReadWriteLock get() {
|
||
|
return new ReentrantReadWriteLock();
|
||
|
}
|
||
|
};
|
||
|
private static final Supplier<ReadWriteLock> WEAK_SAFE_READ_WRITE_LOCK_SUPPLIER = new Supplier<ReadWriteLock>() { // from class: com.google.common.util.concurrent.Striped.6
|
||
|
@Override // com.google.common.base.Supplier
|
||
|
public ReadWriteLock get() {
|
||
|
return new WeakSafeReadWriteLock();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/* JADX INFO: Access modifiers changed from: private */
|
||
|
public static int smear(int i) {
|
||
|
int i2 = i ^ ((i >>> 20) ^ (i >>> 12));
|
||
|
return (i2 ^ (i2 >>> 7)) ^ (i2 >>> 4);
|
||
|
}
|
||
|
|
||
|
public abstract L get(Object obj);
|
||
|
|
||
|
public abstract L getAt(int i);
|
||
|
|
||
|
abstract int indexFor(Object obj);
|
||
|
|
||
|
public abstract int size();
|
||
|
|
||
|
private Striped() {
|
||
|
}
|
||
|
|
||
|
public Iterable<L> bulkGet(Iterable<?> iterable) {
|
||
|
Object[] array = Iterables.toArray(iterable, Object.class);
|
||
|
if (array.length == 0) {
|
||
|
return ImmutableList.of();
|
||
|
}
|
||
|
int[] iArr = new int[array.length];
|
||
|
for (int i = 0; i < array.length; i++) {
|
||
|
iArr[i] = indexFor(array[i]);
|
||
|
}
|
||
|
Arrays.sort(iArr);
|
||
|
int i2 = iArr[0];
|
||
|
array[0] = getAt(i2);
|
||
|
for (int i3 = 1; i3 < array.length; i3++) {
|
||
|
int i4 = iArr[i3];
|
||
|
if (i4 == i2) {
|
||
|
array[i3] = array[i3 - 1];
|
||
|
} else {
|
||
|
array[i3] = getAt(i4);
|
||
|
i2 = i4;
|
||
|
}
|
||
|
}
|
||
|
return Collections.unmodifiableList(Arrays.asList(array));
|
||
|
}
|
||
|
|
||
|
static <L> Striped<L> custom(int i, Supplier<L> supplier) {
|
||
|
return new CompactStriped(i, supplier);
|
||
|
}
|
||
|
|
||
|
public static Striped<Lock> lock(int i) {
|
||
|
return custom(i, new Supplier<Lock>() { // from class: com.google.common.util.concurrent.Striped.1
|
||
|
@Override // com.google.common.base.Supplier
|
||
|
public Lock get() {
|
||
|
return new PaddedLock();
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
public static Striped<Lock> lazyWeakLock(int i) {
|
||
|
return lazy(i, new Supplier<Lock>() { // from class: com.google.common.util.concurrent.Striped.2
|
||
|
@Override // com.google.common.base.Supplier
|
||
|
public Lock get() {
|
||
|
return new ReentrantLock(false);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
private static <L> Striped<L> lazy(int i, Supplier<L> supplier) {
|
||
|
if (i < 1024) {
|
||
|
return new SmallLazyStriped(i, supplier);
|
||
|
}
|
||
|
return new LargeLazyStriped(i, supplier);
|
||
|
}
|
||
|
|
||
|
public static Striped<Semaphore> semaphore(int i, int i2) {
|
||
|
return custom(i, new Supplier<Semaphore>(i2) { // from class: com.google.common.util.concurrent.Striped.3
|
||
|
final int val$permits;
|
||
|
|
||
|
{
|
||
|
this.val$permits = i2;
|
||
|
}
|
||
|
|
||
|
@Override // com.google.common.base.Supplier
|
||
|
public Semaphore get() {
|
||
|
return new PaddedSemaphore(this.val$permits);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
public static Striped<Semaphore> lazyWeakSemaphore(int i, int i2) {
|
||
|
return lazy(i, new Supplier<Semaphore>(i2) { // from class: com.google.common.util.concurrent.Striped.4
|
||
|
final int val$permits;
|
||
|
|
||
|
{
|
||
|
this.val$permits = i2;
|
||
|
}
|
||
|
|
||
|
@Override // com.google.common.base.Supplier
|
||
|
public Semaphore get() {
|
||
|
return new Semaphore(this.val$permits, false);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
public static Striped<ReadWriteLock> readWriteLock(int i) {
|
||
|
return custom(i, READ_WRITE_LOCK_SUPPLIER);
|
||
|
}
|
||
|
|
||
|
public static Striped<ReadWriteLock> lazyWeakReadWriteLock(int i) {
|
||
|
return lazy(i, WEAK_SAFE_READ_WRITE_LOCK_SUPPLIER);
|
||
|
}
|
||
|
|
||
|
/* JADX INFO: Access modifiers changed from: package-private */
|
||
|
/* loaded from: classes2.dex */
|
||
|
public static final class WeakSafeReadWriteLock implements ReadWriteLock {
|
||
|
private final ReadWriteLock delegate = new ReentrantReadWriteLock();
|
||
|
|
||
|
WeakSafeReadWriteLock() {
|
||
|
}
|
||
|
|
||
|
@Override // java.util.concurrent.locks.ReadWriteLock
|
||
|
public final Lock readLock() {
|
||
|
return new WeakSafeLock(this.delegate.readLock(), this);
|
||
|
}
|
||
|
|
||
|
@Override // java.util.concurrent.locks.ReadWriteLock
|
||
|
public final Lock writeLock() {
|
||
|
return new WeakSafeLock(this.delegate.writeLock(), this);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes2.dex */
|
||
|
static final class WeakSafeLock extends ForwardingLock {
|
||
|
private final Lock delegate;
|
||
|
private final WeakSafeReadWriteLock strongReference;
|
||
|
|
||
|
WeakSafeLock(Lock lock, WeakSafeReadWriteLock weakSafeReadWriteLock) {
|
||
|
this.delegate = lock;
|
||
|
this.strongReference = weakSafeReadWriteLock;
|
||
|
}
|
||
|
|
||
|
@Override // com.google.common.util.concurrent.ForwardingLock, java.util.concurrent.locks.Lock
|
||
|
public final Condition newCondition() {
|
||
|
return new WeakSafeCondition(this.delegate.newCondition(), this.strongReference);
|
||
|
}
|
||
|
|
||
|
@Override // com.google.common.util.concurrent.ForwardingLock
|
||
|
final Lock delegate() {
|
||
|
return this.delegate;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes2.dex */
|
||
|
static final class WeakSafeCondition extends ForwardingCondition {
|
||
|
private final Condition delegate;
|
||
|
private final WeakSafeReadWriteLock strongReference;
|
||
|
|
||
|
WeakSafeCondition(Condition condition, WeakSafeReadWriteLock weakSafeReadWriteLock) {
|
||
|
this.delegate = condition;
|
||
|
this.strongReference = weakSafeReadWriteLock;
|
||
|
}
|
||
|
|
||
|
@Override // com.google.common.util.concurrent.ForwardingCondition
|
||
|
final Condition delegate() {
|
||
|
return this.delegate;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* loaded from: classes2.dex */
|
||
|
static abstract class PowerOfTwoStriped<L> extends Striped<L> {
|
||
|
final int mask;
|
||
|
|
||
|
PowerOfTwoStriped(int i) {
|
||
|
super();
|
||
|
Preconditions.checkArgument(i > 0, "Stripes must be positive");
|
||
|
this.mask = i > 1073741824 ? -1 : Striped.ceilToPowerOfTwo(i) - 1;
|
||
|
}
|
||
|
|
||
|
@Override // com.google.common.util.concurrent.Striped
|
||
|
final int indexFor(Object obj) {
|
||
|
return Striped.smear(obj.hashCode()) & this.mask;
|
||
|
}
|
||
|
|
||
|
@Override // com.google.common.util.concurrent.Striped
|
||
|
public final L get(Object obj) {
|
||
|
return getAt(indexFor(obj));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* JADX INFO: Access modifiers changed from: package-private */
|
||
|
/* loaded from: classes2.dex */
|
||
|
public static class CompactStriped<L> extends PowerOfTwoStriped<L> {
|
||
|
private final Object[] array;
|
||
|
|
||
|
private CompactStriped(int i, Supplier<L> supplier) {
|
||
|
super(i);
|
||
|
int i2 = 0;
|
||
|
Preconditions.checkArgument(i <= 1073741824, "Stripes must be <= 2^30)");
|
||
|
this.array = new Object[this.mask + 1];
|
||
|
while (true) {
|
||
|
Object[] objArr = this.array;
|
||
|
if (i2 >= objArr.length) {
|
||
|
return;
|
||
|
}
|
||
|
objArr[i2] = supplier.get();
|
||
|
i2++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override // com.google.common.util.concurrent.Striped
|
||
|
public L getAt(int i) {
|
||
|
return (L) this.array[i];
|
||
|
}
|
||
|
|
||
|
@Override // com.google.common.util.concurrent.Striped
|
||
|
public int size() {
|
||
|
return this.array.length;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* JADX INFO: Access modifiers changed from: package-private */
|
||
|
/* loaded from: classes2.dex */
|
||
|
public static class SmallLazyStriped<L> extends PowerOfTwoStriped<L> {
|
||
|
final AtomicReferenceArray<ArrayReference<? extends L>> locks;
|
||
|
final ReferenceQueue<L> queue;
|
||
|
final int size;
|
||
|
final Supplier<L> supplier;
|
||
|
|
||
|
SmallLazyStriped(int i, Supplier<L> supplier) {
|
||
|
super(i);
|
||
|
this.queue = new ReferenceQueue<>();
|
||
|
int i2 = this.mask == -1 ? Integer.MAX_VALUE : this.mask + 1;
|
||
|
this.size = i2;
|
||
|
this.locks = new AtomicReferenceArray<>(i2);
|
||
|
this.supplier = supplier;
|
||
|
}
|
||
|
|
||
|
@Override // com.google.common.util.concurrent.Striped
|
||
|
public L getAt(int i) {
|
||
|
if (this.size != Integer.MAX_VALUE) {
|
||
|
Preconditions.checkElementIndex(i, size());
|
||
|
}
|
||
|
ArrayReference<? extends L> arrayReference = this.locks.get(i);
|
||
|
L l = arrayReference == null ? null : arrayReference.get();
|
||
|
if (l != null) {
|
||
|
return l;
|
||
|
}
|
||
|
L l2 = this.supplier.get();
|
||
|
ArrayReference arrayReference2 = new ArrayReference(l2, i, this.queue);
|
||
|
while (!Striped$SmallLazyStriped$$ExternalSyntheticBackportWithForwarding0.m(this.locks, i, arrayReference, arrayReference2)) {
|
||
|
arrayReference = this.locks.get(i);
|
||
|
L l3 = arrayReference == null ? null : arrayReference.get();
|
||
|
if (l3 != null) {
|
||
|
return l3;
|
||
|
}
|
||
|
}
|
||
|
drainQueue();
|
||
|
return l2;
|
||
|
}
|
||
|
|
||
|
private void drainQueue() {
|
||
|
while (true) {
|
||
|
Reference<? extends L> poll = this.queue.poll();
|
||
|
if (poll == null) {
|
||
|
return;
|
||
|
}
|
||
|
ArrayReference arrayReference = (ArrayReference) poll;
|
||
|
Striped$SmallLazyStriped$$ExternalSyntheticBackportWithForwarding0.m(this.locks, arrayReference.index, arrayReference, null);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* JADX INFO: Access modifiers changed from: package-private */
|
||
|
/* loaded from: classes2.dex */
|
||
|
public static final class ArrayReference<L> extends WeakReference<L> {
|
||
|
final int index;
|
||
|
|
||
|
ArrayReference(L l, int i, ReferenceQueue<L> referenceQueue) {
|
||
|
super(l, referenceQueue);
|
||
|
this.index = i;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override // com.google.common.util.concurrent.Striped
|
||
|
public int size() {
|
||
|
return this.size;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* JADX INFO: Access modifiers changed from: package-private */
|
||
|
/* loaded from: classes2.dex */
|
||
|
public static class LargeLazyStriped<L> extends PowerOfTwoStriped<L> {
|
||
|
final ConcurrentMap<Integer, L> locks;
|
||
|
final int size;
|
||
|
final Supplier<L> supplier;
|
||
|
|
||
|
LargeLazyStriped(int i, Supplier<L> supplier) {
|
||
|
super(i);
|
||
|
this.size = this.mask == -1 ? Integer.MAX_VALUE : this.mask + 1;
|
||
|
this.supplier = supplier;
|
||
|
this.locks = new MapMaker().weakValues().makeMap();
|
||
|
}
|
||
|
|
||
|
@Override // com.google.common.util.concurrent.Striped
|
||
|
public L getAt(int i) {
|
||
|
if (this.size != Integer.MAX_VALUE) {
|
||
|
Preconditions.checkElementIndex(i, size());
|
||
|
}
|
||
|
L l = this.locks.get(Integer.valueOf(i));
|
||
|
if (l != null) {
|
||
|
return l;
|
||
|
}
|
||
|
L l2 = this.supplier.get();
|
||
|
return (L) MoreObjects.firstNonNull(this.locks.putIfAbsent(Integer.valueOf(i), l2), l2);
|
||
|
}
|
||
|
|
||
|
@Override // com.google.common.util.concurrent.Striped
|
||
|
public int size() {
|
||
|
return this.size;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* JADX INFO: Access modifiers changed from: private */
|
||
|
public static int ceilToPowerOfTwo(int i) {
|
||
|
return 1 << IntMath.log2(i, RoundingMode.CEILING);
|
||
|
}
|
||
|
|
||
|
/* JADX INFO: Access modifiers changed from: package-private */
|
||
|
/* loaded from: classes2.dex */
|
||
|
public static class PaddedLock extends ReentrantLock {
|
||
|
long unused1;
|
||
|
long unused2;
|
||
|
long unused3;
|
||
|
|
||
|
PaddedLock() {
|
||
|
super(false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* JADX INFO: Access modifiers changed from: package-private */
|
||
|
/* loaded from: classes2.dex */
|
||
|
public static class PaddedSemaphore extends Semaphore {
|
||
|
long unused1;
|
||
|
long unused2;
|
||
|
long unused3;
|
||
|
|
||
|
PaddedSemaphore(int i) {
|
||
|
super(i, false);
|
||
|
}
|
||
|
}
|
||
|
}
|