package edu.washington.escience.myria.util;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Util methods for atomic variables, mainly for bitwise operations.
* */
public final class AtomicUtils {
/**
* Make the util class uninstantiable.
* */
private AtomicUtils() {}
/**
* Atomically do bitwise OR between the value in the AtomicInteger and the toOrValue, and set the new value to the
* AtomicInteger and also return the new value.
*
* @param ai the atomic variable to operate on
* @param toOrValue the value to do the OR operation
* @return the new value.
* */
public static int bitwiseOrAndGet(final AtomicInteger ai, final int toOrValue) {
int oldValue = ai.get();
int newValue = oldValue | toOrValue;
while (oldValue != newValue && !ai.compareAndSet(oldValue, newValue)) {
oldValue = ai.get();
newValue = oldValue | toOrValue;
}
return newValue;
}
/**
* Atomically do bitwise AND between the value in the AtomicInteger and the toAndValue, and set the new value to the
* AtomicInteger and also return the new value.
*
* @param ai the atomic variable to operate on
* @param toAndValue the value to do the OR operation
* @return the new value.
* */
public static int bitwiseAndAndGet(final AtomicInteger ai, final int toAndValue) {
int oldValue = ai.get();
int newValue = oldValue & toAndValue;
while (oldValue != newValue && !ai.compareAndSet(oldValue, newValue)) {
oldValue = ai.get();
newValue = oldValue & toAndValue;
}
return newValue;
}
/**
* @return true if operation is conducted, false if the bit is already unset.
* @param ai the AtomicInteger to operate on
* @param n the nth bit from the least significant bit to compare, the least significant bit is 0
* */
public static boolean unsetBitIfSetByIndex(final AtomicInteger ai, final int n) {
if (n >= Integer.SIZE) {
throw new IllegalArgumentException("Out of int bit index boundary (31)");
}
int bitInt = 1 << n;
int oldValue = ai.get();
int newValue = oldValue & ~bitInt;
while (newValue != oldValue && !ai.compareAndSet(oldValue, newValue)) {
oldValue = ai.get();
newValue = oldValue & ~bitInt;
}
return newValue != oldValue;
}
/**
* @return true if operation is conducted, false if the bit is already set.
* @param ai the AtomicInteger to operate on
* @param value from the value get the index of the set bit from the least significant bit. Do the operation on that
* index.
* */
public static boolean unsetBitIfSetByValue(final AtomicInteger ai, final int value) {
return unsetBitIfSetByIndex(ai, Integer.numberOfTrailingZeros(value));
}
/**
* @return true if operation is conducted, false if the bit is already set.
* @param ai the AtomicInteger to operate on
* @param n the nth bit from the least significant bit to compare
* */
public static boolean setBitIfUnsetByIndex(final AtomicInteger ai, final int n) {
if (n >= Integer.SIZE) {
throw new IllegalArgumentException("Out of int bit index boundary (31)");
}
int bitInt = 1 << n;
int oldValue = ai.get();
int newValue = oldValue | bitInt;
while (newValue != oldValue && !ai.compareAndSet(oldValue, newValue)) {
oldValue = ai.get();
newValue = oldValue | bitInt;
}
return newValue != oldValue;
}
/**
* @return true if operation is conducted, false if the bit is already set.
* @param ai the AtomicInteger to operate on
* @param value from the value get the index of the set bit from the least significant bit. Do the operation on that
* index.
* */
public static boolean setBitIfUnsetByValue(final AtomicInteger ai, final int value) {
return setBitIfUnsetByIndex(ai, Integer.numberOfTrailingZeros(value));
}
/**
* @param ai the AtomicInteger to operate on
* @param n the nth bit from the least significant bit to compare
* */
public static void setBitByIndex(final AtomicInteger ai, final int n) {
setBitIfUnsetByIndex(ai, n);
}
/**
* @param ai the AtomicInteger to operate on
* @param value from the value get the index of the set bit from the least significant bit. Do the operation on that
* index.
* */
public static void setBitByValue(final AtomicInteger ai, final int value) {
setBitByIndex(ai, Integer.numberOfTrailingZeros(value));
}
/**
* @param ai the AtomicInteger to operate on
* @param n the nth bit from the least significant bit to compare
* */
public static void unsetBitByIndex(final AtomicInteger ai, final int n) {
unsetBitIfSetByIndex(ai, n);
}
/**
* @param ai the AtomicInteger to operate on
* @param value from the value get the index of the set bit from the least significant bit. Do the operation on that
* index.
* */
public static void unsetBitByValue(final AtomicInteger ai, final int value) {
unsetBitByIndex(ai, Integer.numberOfTrailingZeros(value));
}
}