@Override public boolean isWriteTransaction() { Cons<ParallelNestedTransaction> emptyCons = Cons.<ParallelNestedTransaction> empty(); return (mergedTxs != emptyCons) || (!boxesWritten.isEmpty()) || (!boxesWrittenInPlace.isEmpty()) || (!arrayWrites.isEmpty()) || (perTxValues != null && !perTxValues.isEmpty()); }
public final E first() { if (isEmpty()) { throw new EmptyListException(); } else { return first; } }
public final Cons<E> rest() { if (isEmpty()) { throw new EmptyListException(); } else { return rest; } }
@Override public boolean isEmpty() { return entries.get().isEmpty(); }
private static VBox[] borrowFromPool() { Cons<VBox[]> available = pool.get(); if (available.isEmpty()) { VBox[] newArray = new VBox[1000]; return newArray; } else { pool.set(available.rest()); return available.first(); } }
@Override protected <T> VBoxBody<T> newerVersionDetected(VBoxBody<T> body) { if (!this.boxesWritten.isEmpty() || !this.boxesWrittenInPlace.isEmpty()) { return super.newerVersionDetected(body); } else { return body.getBody(number); } }
@Override @Atomic(readOnly = true) public E element() { Cons<E> frontElems = front.get(); if (frontElems.isEmpty()) { throw new NoSuchElementException(); } else { return frontElems.first(); } }
@Override public void remove() { throw new UnsupportedOperationException(); } }
private SimpleReadSet makeSimpleReadSet() { HashSet<String> vboxIds = new HashSet<String>(); if (!this.bodiesRead.isEmpty()) { // the first may not be full jvstm.VBox[] array = this.bodiesRead.first(); for (int i = next + 1; i < array.length; i++) { String vboxId = ((VBox) array[i]).getId(); vboxIds.add(vboxId); } // the rest are full for (jvstm.VBox[] ar : bodiesRead.rest()) { for (int i = 0; i < ar.length; i++) { String vboxId = ((VBox) array[i]).getId(); vboxIds.add(vboxId); } } } return new SimpleReadSet(vboxIds.toArray(new String[vboxIds.size()])); }
@Override protected void snapshotValidation(int lastSeenNumber) { if (retrieveAncestorVersion(parent) == lastSeenNumber) { return; } for (Map.Entry<VBox, InplaceWrite> read : nestedReads.entrySet()) { validateNestedRead(read); } for (ParallelNestedTransaction mergedTx : mergedTxs) { for (Map.Entry<VBox, InplaceWrite> read : mergedTx.nestedReads.entrySet()) { validateNestedRead(read); } } if (!this.globalReads.isEmpty()) { validateGlobalReads(globalReads, next); } for (ParallelNestedTransaction mergedTx : mergedTxs) { if (!mergedTx.globalReads.isEmpty()) { validateGlobalReads(mergedTx.globalReads, mergedTx.next); } } }
@Override @Atomic(readOnly = true) public E peek() { Cons<E> frontElems = front.get(); if (frontElems.isEmpty()) { return null; } else { return frontElems.first(); } }
@Override @Atomic(canFail = false) public E poll() { Cons<E> frontElems = front.get(); if (frontElems.isEmpty()) { return null; } else { return removeExisting(frontElems); } }
@Override protected void tryCommit() { ReadWriteTransaction parent = getRWParent(); Cons<ParallelNestedTransaction> currentOrecs; Cons<ParallelNestedTransaction> modifiedOrecs; do { currentOrecs = parent.mergedTxs; modifiedOrecs = currentOrecs.cons(this); } while (!parent.CASmergedTxs(currentOrecs, modifiedOrecs)); if (!this.arraysRead.isEmpty()) { synchronized (parent) { // the possible array writes are already placed in the parent parent.arraysRead = this.arraysRead.reverseInto(parent.arraysRead); } } Transaction.current.set(null); }
private E removeExisting(Cons<E> frontElems) { E result = frontElems.first(); frontElems = frontElems.rest(); if (frontElems.isEmpty()) { frontElems = rear.get().reverse(); if (!frontElems.isEmpty()) { // only clear the rear if it had anything rear.put((Cons<E>) Cons.empty()); } } front.put(frontElems); size.dec(); return result; }
@Override protected void tryCommit() { ReadWriteTransaction parent = getRWParent(); Cons<ParallelNestedTransaction> currentOrecs; Cons<ParallelNestedTransaction> modifiedOrecs; do { currentOrecs = parent.mergedTxs; modifiedOrecs = currentOrecs.cons(this); for (ParallelNestedTransaction child : mergedTxs) { modifiedOrecs = modifiedOrecs.cons(child); } } while (!parent.CASmergedTxs(currentOrecs, modifiedOrecs)); if (!this.arraysRead.isEmpty()) { synchronized (parent) { parent.arraysRead = this.arraysRead.reverseInto(parent.arraysRead); } } }
protected boolean isSnapshotValidationWorthIt(ActiveTransactionsRecord lastRecord) { if (this.bodiesRead.isEmpty()) { return false; } int numberOfReadsToCheck = this.bodiesRead.first().length - (next + 1); // if there are more arrays the rest are full, for sure for (VBox[] array : bodiesRead.rest()) { numberOfReadsToCheck += array.length; } int numberOfWritesToCheck = 0; for (ActiveTransactionsRecord rec = this.activeTxRecord.getNext(); rec != null; rec = rec.getNext()) { numberOfWritesToCheck += rec.getWriteSet().size(); } return ((float) numberOfWritesToCheck) / numberOfReadsToCheck > WR_THRESHOLD; }
@Override @Atomic(canFail = false) public boolean offer(E o) { Cons<E> frontElems = front.get(); if (frontElems.isEmpty()) { front.put(frontElems.cons(o)); } else { rear.put(rear.get().cons(o)); } size.inc(); return true; }