@Override public void beforeReadAccess(Object obj, long field) { if (vr) { readHash = LockTable.hash(obj, field); // Lock entry in read mode (might throw an exception) readLock = LockTable.lock(this, readHash, id, false); if (readLock >= 0) { synchronized (writeSet) { // Mutual exclusion on write set to allow other transaction to drop locks if ((status.get() & STATUS_MASK) != TX_ACTIVE) { // We have been killed: drop lock we just acquired (not in write set) LockTable.setAndReleaseLock(readHash, readLock); // Abort throw KILLED_EXCEPTION; } // Add to write set (for being able to drop lock later) writeSet.addRead(readHash, obj, field, readLock); } } } else { readHash = LockTable.hash(obj, field); // Check if the field is locked (may throw an exception) readLock = LockTable.checkLock(this, readHash, id); } }
private void onWriteAccess(Object obj, long field, Object value, Type type) { if (!readWriteHint) { // Change hint to read-write readWriteMarkers.insert(atomicBlockId, true); throw READ_ONLY_FAILURE_EXCEPTION; } int hash = LockTable.hash(obj, field); // Lock entry in write mode (might throw an exception) long timestamp = LockTable.lock(this, hash, id, true); synchronized (writeSet) { // Mutual exclusion on write set to allow other transaction to drop locks if ((status.get() & STATUS_MASK) != TX_ACTIVE) { // We have been killed if (timestamp >= 0) { // Drop lock we just acquired (not in write set) LockTable.setAndReleaseLock(hash, timestamp); } // Abort throw KILLED_EXCEPTION; } if (timestamp < 0) { // We already own that lock writeSet.appendWrite(hash, obj, field, value, type); } else { // Add to write set if (timestamp > endTime) { // Handle write-after-read if (readSet.contains(obj, field)) { // Abort LockTable.setAndReleaseLock(hash, timestamp); throw WRITE_FAILURE_EXCEPTION; } // We delay validation until later (although we could already validate once here) } // Add to write set writeSet.addWrite(hash, obj, field, value, type, timestamp); } } }