/// <summary> /// Try taking a concurrent write lock. Multiple write locks can be held at the same time. Write locks will /// invalidate any optimistic read lock that overlaps with them, and write locks will make any attempt at grabbing /// an exclusive lock fail. If an exclusive lock is currently held, then the attempt to take a write lock will fail. /// <para> /// Write locks must be paired with a corresponding <seealso cref="unlockWrite(long)"/>. /// /// </para> /// </summary> /// <returns> {@code true} if the write lock was taken, {@code false} otherwise. </returns> public static bool TryWriteLock(long address) { long s; long n; for ( ; ;) { s = GetState(address); bool unwritablyLocked = (s & _exlMask) != 0; bool writeCountOverflow = (s & _cntMask) == _cntMask; // bitwise-OR to reduce branching and allow more ILP if (unwritablyLocked | writeCountOverflow) { return(FailWriteLock(s, writeCountOverflow)); } n = s + _cntUnit | _modMask; if (CompareAndSetState(address, s, n)) { UnsafeUtil.storeFence(); return(true); } } }
/// <summary> /// Grab the exclusive lock if it is immediately available. Exclusive locks will invalidate any overlapping /// optimistic read lock, and fail write and flush locks. If any write or flush locks are currently taken, or if /// the exclusive lock is already taken, then the attempt to grab an exclusive lock will fail. /// <para> /// Successfully grabbed exclusive locks must always be paired with a corresponding <seealso cref="unlockExclusive(long)"/>. /// /// </para> /// </summary> /// <returns> {@code true} if we successfully got the exclusive lock, {@code false} otherwise. </returns> public static bool TryExclusiveLock(long address) { long s = GetState(address); bool res = ((s & _unlMask) == 0) && CompareAndSetState(address, s, s + _exlMask); UnsafeUtil.storeFence(); return(res); }
/// <summary> /// Grab the flush lock if it is immediately available. Flush locks prevent overlapping exclusive locks, /// but do not invalidate optimistic read locks, nor do they prevent overlapping write locks. Only one flush lock /// can be held at a time. If any flush or exclusive lock is already held, the attempt to take the flush lock will /// fail. /// <para> /// Successfully grabbed flush locks must always be paired with a corresponding /// <seealso cref="unlockFlush(long, long, bool)"/>. /// /// </para> /// </summary> /// <returns> If the lock is successfully grabbed, the method will return a stamp value that must be passed to the /// <seealso cref="unlockFlush(long, long, bool)"/>, and which is used for detecting any overlapping write locks. If the /// flush lock could not be taken, {@code 0} will be returned. </returns> public static long TryFlushLock(long address) { long s = GetState(address); if ((s & _faeMask) == 0) { long n = s + _flsMask; bool res = CompareAndSetState(address, s, n); UnsafeUtil.storeFence(); return(res ? n : 0); } return(0); }
public static long UnlockWriteAndTryTakeFlushLock(long address) { long s; long n; long r; do { r = 0; s = GetState(address); if ((s & _cntMask) == 0) { ThrowUnmatchedUnlockWrite(s); } n = NextSeq(s) - _cntUnit; if ((n & _faeMask) == 0) { n += _flsMask; r = n; } } while (!CompareAndSetState(address, s, n)); UnsafeUtil.storeFence(); return(r); }