void unlockLastToUpgradable(Locker locker) { Lock[] locks = mLocks; int size = mSize; locker.mManager.unlockToUpgradable(locker, locks[--size]); long upgrades = mUpgrades; long mask = 1L << size; if ((upgrades & mask) != 0) { // Pop upgrade off stack, but only if unlock succeeded. locks[size] = null; if (size == 0) { locker.mTailBlock = mPrev; mPrev = null; } else { mUpgrades = upgrades & ~mask; mSize = size; } } }
void unlockLastToUpgradable(Locker locker) { Lock[] locks = mLocks; int size = mSize; locker.mManager.unlockToUpgradable(locker, locks[--size]); long upgrades = mUpgrades; long mask = 1L << size; if ((upgrades & mask) != 0) { // Pop upgrade off stack, but only if unlock succeeded. locks[size] = null; if (size == 0) { locker.mTailBlock = mPrev; mPrev = null; } else { mUpgrades = upgrades & ~mask; mSize = size; } } }
/** * Releases last lock acquired or upgraded, within the current scope, * retaining an upgradable lock. * * <p><i>Note: This method is intended for advanced use cases.</i> Also, the current * implementation does not accurately track scopes. It may permit an unlock operation to * cross a scope boundary, which has undefined behavior. * * @throws IllegalStateException if no locks held, or if last lock is shared */ public final void unlockToUpgradable() { Object tailObj = mTailBlock; if (tailObj == null) { throw new IllegalStateException("No locks held"); } if (tailObj instanceof Lock) { mManager.unlockToUpgradable(this, (Lock) tailObj); } else { ((Block) tailObj).unlockLastToUpgradable(this); } }
/** * Releases the last lock or group acquired or upgraded, within the current scope, * retaining an upgradable lock. * * <p><i>Note: This method is intended for advanced use cases.</i> * * @throws IllegalStateException if no locks held, or if crossing a scope boundary, or if * last lock is shared */ public final void unlockToUpgradable() { Object tailObj = mTailBlock; if (tailObj == null) { throw new IllegalStateException("No locks held"); } if (tailObj instanceof Lock) { ParentScope parent = mParentScope; if (parent != null && parent.mTailBlock == tailObj) { throw new IllegalStateException("Cannot cross a scope boundary"); } mManager.unlockToUpgradable(this, (Lock) tailObj); } else { Block.unlockLastToUpgradable((Block) tailObj, this); } }
/** * Releases last lock acquired or upgraded, within the current scope, * retaining an upgradable lock. * * <p><i>Note: This method is intended for advanced use cases.</i> Also, the current * implementation does not accurately track scopes. It may permit an unlock operation to * cross a scope boundary, which has undefined behavior. * * @throws IllegalStateException if no locks held, or if last lock is shared */ public final void unlockToUpgradable() { Object tailObj = mTailBlock; if (tailObj == null) { throw new IllegalStateException("No locks held"); } if (tailObj instanceof Lock) { mManager.unlockToUpgradable(this, (Lock) tailObj); } else { ((Block) tailObj).unlockLastToUpgradable(this); } }
/** * Note: If target size is zero, caller MUST pop and discard the block. Otherwise, the * block size will be zero, which is illegal. */ void unlockToSavepoint(Locker locker, int targetSize) { int size = mSize; if (size > targetSize) { Lock[] locks = mLocks; LockManager manager = locker.mManager; size--; long mask = 1L << size; long upgrades = mUpgrades; while (true) { Lock lock = locks[size]; if ((upgrades & mask) != 0) { manager.unlockToUpgradable(locker, lock); } else { manager.unlock(locker, lock); } locks[size] = null; if (size == targetSize) { break; } size--; mask >>>= 1; } mUpgrades = upgrades & ~(~0L << size); mSize = size; } }
/** * Note: If target size is zero, caller MUST pop and discard the block. Otherwise, the * block size will be zero, which is illegal. */ void unlockToSavepoint(Locker locker, int targetSize) { int size = mSize; if (size > targetSize) { Lock[] locks = mLocks; LockManager manager = locker.mManager; size--; long mask = 1L << size; long upgrades = mUpgrades; while (true) { Lock lock = locks[size]; if ((upgrades & mask) != 0) { manager.unlockToUpgradable(locker, lock); } else { manager.unlock(locker, lock); } locks[size] = null; if (size == targetSize) { break; } size--; mask >>>= 1; } mUpgrades = upgrades & ~(~0L << size); mSize = size; } }
/** * Note: If target size is zero, caller MUST pop and discard the block. Otherwise, the * block size will be zero, which is illegal. */ void unlockToSavepoint(Locker locker, int targetSize) { int size = mSize; if (size > targetSize) { Lock[] locks = mLocks; LockManager manager = locker.mManager; size--; long mask = (1L << 63) >>> size; long upgrades = mUpgrades; while (true) { Lock lock = locks[size]; if ((upgrades & mask) != 0) { manager.unlockToUpgradable(locker, lock); } else { manager.unlock(locker, lock); } locks[size] = null; if (size == targetSize) { break; } size--; mask <<= 1; } mUpgrades = upgrades & ~(~0L >>> size); mSize = size; } }
block.parentCheck(locker, lock); locker.mManager.unlockToUpgradable(locker, lock);