public E getValue(int maxVersion) { // Keep read value for later validation object = getInternalValue(maxVersion); return object; }
public <T> T getArrayValue(VArrayEntry<T> entry) { return entry.getValue(number); }
protected <T> T getLocalArrayValue(VArrayEntry<T> entry) { T value = null; if (arrayWrites != EMPTY_MAP) { VArrayEntry<T> wsEntry = (VArrayEntry<T>) arrayWrites.get(entry); if (wsEntry != null) { value = (wsEntry.getWriteValue() == null ? (T) NULL_VALUE : wsEntry.getWriteValue()); } } if ((value == null) && (parent != null)) { value = getRWParent().getLocalArrayValue(entry); } return value; }
@Override protected <T> T getLocalArrayValue(VArrayEntry<T> entry) { if (this.arrayWrites != EMPTY_MAP) { VArrayEntry<T> wsEntry = (VArrayEntry<T>) this.arrayWrites.get(entry); if (wsEntry != null) { return (wsEntry.getWriteValue() == null ? (T) NULL_VALUE : wsEntry.getWriteValue()); } } ReadWriteTransaction iter = getRWParent(); while (iter != null) { synchronized (iter) { if (iter.arrayWrites != EMPTY_MAP) { VArrayEntry<T> wsEntry = (VArrayEntry<T>) iter.arrayWrites.get(entry); if (wsEntry == null) { iter = iter.getRWParent(); continue; } if (wsEntry.nestedVersion <= retrieveAncestorVersion(iter)) { this.arraysRead = this.arraysRead.cons(entry); entry.setReadOwner(iter); return (wsEntry.getWriteValue() == null ? (T) NULL_VALUE : wsEntry.getWriteValue()); } else { TransactionSignaller.SIGNALLER.signalCommitFail(iter); } } } iter = iter.getRWParent(); } return null; }
@SuppressWarnings("static-access") public void put(int index, E newE) { rangeCheck(index); Transaction tx = Transaction.current(); if (tx == null) { tx = Transaction.begin(); tx.setArrayValue(new VArrayEntry<E>(this, index), newE); tx.commit(); } else { tx.setArrayValue(new VArrayEntry<E>(this, index), newE); } }
@Override public <T> void setArrayValue(VArrayEntry<T> entry, T value) { if (arrayWrites == EMPTY_MAP) { arrayWrites = new IdentityHashMap<VArrayEntry<?>, VArrayEntry<?>>(); arrayWritesCount = new IdentityHashMap<VArray<?>, Integer>(); } entry.setWriteValue(value, this.nestedCommitQueue.commitNumber); if (arrayWrites.put(entry, entry) != null) { return; } // Count number of writes to the array Integer writeCount = arrayWritesCount.get(entry.array); if (writeCount == null) { writeCount = 0; } arrayWritesCount.put(entry.array, writeCount + 1); }
if (!entry.validate()) { TransactionSignaller.SIGNALLER.signalCommitFail();
@SuppressWarnings("static-access") public E get(int index) { rangeCheck(index); // TODO: Apply the same optimization as in VBox.get() Transaction tx = Transaction.current(); if (tx == null) { tx = Transaction.begin(true); E value = tx.getArrayValue(new VArrayEntry<E>(this, index)); tx.commit(); return value; } else { return tx.getArrayValue(new VArrayEntry<E>(this, index)); } }
@Override public <T> void setArrayValue(VArrayEntry<T> entry, T value) { ReadWriteTransaction parent = getRWParent(); synchronized (parent) { if (parent.arrayWrites == EMPTY_MAP) { parent.arrayWrites = new HashMap<VArrayEntry<?>, VArrayEntry<?>>(); parent.arrayWritesCount = new HashMap<VArray<?>, Integer>(); } entry.setWriteValue(value, parent.nestedCommitQueue.commitNumber); if (parent.arrayWrites.put(entry, entry) != null) return; // Count number of writes to the array Integer writeCount = parent.arrayWritesCount.get(entry.array); if (writeCount == null) writeCount = 0; parent.arrayWritesCount.put(entry.array, writeCount + 1); } }
@Override protected <T> T getLocalArrayValue(VArrayEntry<T> entry) { ReadWriteTransaction iter = getRWParent(); while (iter != null) { synchronized (iter) { if (iter.arrayWrites != EMPTY_MAP) { VArrayEntry<T> wsEntry = (VArrayEntry<T>) iter.arrayWrites.get(entry); if (wsEntry != null) { return (wsEntry.getWriteValue() == null ? (T) NULL_VALUE : wsEntry.getWriteValue()); } } } iter = iter.getRWParent(); } return null; }
@Override public <T> T getArrayValue(VArrayEntry<T> entry) { T value = getLocalArrayValue(entry); if (value == null) { value = entry.getValue(number); arraysRead = arraysRead.cons(entry); } return (value == NULL_VALUE) ? null : value; }
@Override protected <T> T getLocalArrayValue(VArrayEntry<T> entry) { ReadWriteTransaction iter = getRWParent(); while (iter != null) { if (iter.arrayWrites != EMPTY_MAP) { VArrayEntry<T> wsEntry = (VArrayEntry<T>) iter.arrayWrites.get(entry); if (wsEntry == null) { iter = iter.getRWParent(); continue; } if (wsEntry.nestedVersion <= retrieveAncestorVersion(iter)) { return (wsEntry.getWriteValue() == null ? (T) NULL_VALUE : wsEntry.getWriteValue()); } } iter = iter.getRWParent(); } return null; }
@SuppressWarnings("unchecked") public GarbageCollectable commit(int txNumber, VArrayEntry[] writesToCommit, int[] logEntryIndexes) { // Prepare arrays for log E[] logEntryValues = (E[]) new Object[writesToCommit.length]; // Create and place log node log = new VArrayLogNode<E>(logEntryIndexes, logEntryValues, txNumber - 1, log); // Bump array version version = txNumber; // Proceed with normal writeback and populating log values int i = 0; for (VArrayEntry<E> entry : writesToCommit) { // Read old value from the array, and copy it to the log E oldValue = values.get(entry.index); if (oldValue == null) oldValue = (E) NULL_VALUE; logEntryValues[i++] = oldValue; // Write the new value // Using a lazySet because we don't need the new value to be seen by other threads // as soon as possible. In fact, it would be nice if only threads with transactions // created after we finish our commit see the new value. // For more details see the java.util.concurrent.atomic package description javadoc. values.lazySet(entry.index, entry.getWriteValue()); // Volatile write! } return log; } }