// 判断这个一维数组是否已经启用, 可能是第一次初始化
if (buckets.get(bucketInd) == null) {
//newLen 一维数组的长度, 取前一个数组长度 * 2
int newLen = 2 * buckets.get(bucketInd - 1).length();
// 设置失败也没关系, 只要有人初始化成功就行
buckets.compareAndSet(bucketInd, null,
new AtomicReferenceArray<E>(newLen));
}
// 在这个一位数组中,我在哪个位置
// 0x80000000是 10000000 00000000 00000000 00000000
// 这句话就是把上述111000, 第一个1变成了0, 得到011000, 即新值的位置.
int idx = (0x80000000>>>zeroNumPos) ^ pos;
// 通过bucketInd与idx来确定元素在二维数组中的位置
// 期望写入的时候, 该位置值是null, 如果非null, 说明其他线程已经写了, 则继续循环.
newd = new Descriptor<E>(desc.size + 1, new WriteDescriptor<E>(
buckets.get(bucketInd), idx, null, e));
// 循环cas设值
} while (!descriptor.compareAndSet(desc, newd));
descriptor.get().completeWrite();
}
/**
* Remove the last element in the vector.
*
* @return element removed
*/
public E pop_back() {
Descriptor<E> desc;
Descriptor<E> newd;
E elem;
do {
desc = descriptor.get();
desc.completeWrite();
int pos = desc.size + FIRST_BUCKET_SIZE - 1;
int bucketInd = Integer.numberOfLeadingZeros(FIRST_BUCKET_SIZE)
- Integer.numberOfLeadingZeros(pos);
int idx = Integer.highestOneBit(pos) ^ pos;
elem = buckets.get(bucketInd).get(idx);
newd = new Descriptor<E>(desc.size - 1, null);
} while (!descriptor.compareAndSet(desc, newd));
return elem;
}
/**
* Get element with the index.
*
* @param index
* index
* @return element with the index
*/
@Override
public E get(int index) {
int pos = index + FIRST_BUCKET_SIZE;
int zeroNumPos = Integer.numberOfLeadingZeros(pos);
int bucketInd = zeroNumFirst - zeroNumPos;
int idx = (0x80000000>>>zeroNumPos) ^ pos;
return buckets.get(bucketInd).get(idx);
}
/**
* Set the element with index to e.
*
* @param index
* index of element to be reset
* @param e
* element to set
*/
/**
* {@inheritDoc}
*/
public E set(int index, E e) {
int pos = index + FIRST_BUCKET_SIZE;
int bucketInd = Integer.numberOfLeadingZeros(FIRST_BUCKET_SIZE)
- Integer.numberOfLeadingZeros(pos);
int idx = Integer.highestOneBit(pos) ^ pos;
AtomicReferenceArray<E> bucket = buckets.get(bucketInd);
while (true) {
E oldV = bucket.get(idx);
if (bucket.compareAndSet(idx, oldV, e))
return oldV;
}
}