/**
* @param <E>
*/
static class WriteDescriptor<E> {
public E oldV;
public E newV;
public AtomicReferenceArray<E> addr;
public int addr_ind;
/**
* Creating a new descriptor.
*
* @param addr Operation address 对哪个数组进行写
* @param addr_ind Index of address 指定index
* @param oldV old operand
* @param newV new operand
*/
public WriteDescriptor(AtomicReferenceArray<E> addr, int addr_ind,
E oldV, E newV) {
this.addr = addr;
this.addr_ind = addr_ind;
this.oldV = oldV;
this.newV = newV;
}
/**
* set newV.
*/
public void doIt() {
// 这边失败后重试的逻辑在另外的代码里.
addr.compareAndSet(addr_ind, oldV, newV);
}
}
/**
* @param <E>
*/
static class Descriptor<E> {
public int size;
volatile WriteDescriptor<E> writeop;
/**
* Create a new descriptor.
*
* @param size Size of the vector
* @param writeop Executor write operation
*/
public Descriptor(int size, WriteDescriptor<E> writeop) {
this.size = size;
this.writeop = writeop;
}
/**
*
*/
public void completeWrite() {
WriteDescriptor<E> tmpOp = writeop;
if (tmpOp != null) {
tmpOp.doIt();
writeop = null; // this is safe since all write to writeop use
// null as r_value.
}
}
}
private AtomicReference<Descriptor<E>> descriptor;
private static final int zeroNumFirst = Integer
.numberOfLeadingZeros(FIRST_BUCKET_SIZE);
/**
* Constructor.
*/
public LockFreeVector() {
buckets = new AtomicReferenceArray<AtomicReferenceArray<E>>(N_BUCKET);
buckets.set(0, new AtomicReferenceArray<E>(FIRST_BUCKET_SIZE));
descriptor = new AtomicReference<Descriptor<E>>(new Descriptor<E>(0,
null));
}
/**
* add e at the end of vector.
* 把元素e加到vector中
*
* @param e
* element added
*/
public void push_back(E e) {
Descriptor<E> desc;
Descriptor<E> newd;
do {
desc = descriptor.get();
desc.completeWrite();
// desc.size Vector 本身的大小
// FIRST_BUCKET_SIZE 第一个一维数组的大小
int pos = desc.size + FIRST_BUCKET_SIZE;
// 取出pos 的前导0
int zeroNumPos = Integer.numberOfLeadingZeros(pos);
// zeroNumFirst 为FIRST_BUCKET_SIZE 的前导0
// bucketInd 数据应该放到哪一个一维数组(篮子)里的
int bucketInd = zeroNumFirst - zeroNumPos;
// 00000000 00000000 00000000 00001000 第一个篮子满 8
// 00000000 00000000 00000000 00011000 第二个篮子满 8 + 16
// 00000000 00000000 00000000 00111000 第三个篮子满 8 + 16 + 32
// ... bucketInd其实通过前导0相减, 就是为了得出来当前第几个篮子是空的.