/** * @param state Lock state. * @return {@code True} if write lock is not acquired. */ private boolean canReadLock(long state) { return lockCount(state) >= 0; }
/** * @param state Lock state. * @return {@code True} if no read locks are acquired. */ private boolean canWriteLock(long state) { return lockCount(state) == 0; }
/** * @param lock Lock to check. * @return {@code True} if at least one read lock is held by any thread for the given offheap RW lock. */ public boolean isReadLocked(long lock) { return lockCount(GridUnsafe.getLongVolatile(null, lock)) > 0; }
/** * @param lock Lock to check. * @return {@code True} if write lock is held by any thread for the given offheap RW lock. */ public boolean isWriteLocked(long lock) { return lockCount(GridUnsafe.getLongVolatile(null, lock)) == -1; }
/** * @param lock Lock address. */ public void readUnlock(long lock) { while (true) { long state = GridUnsafe.getLongVolatile(null, lock); if (lockCount(state) <= 0) throw new IllegalMonitorStateException("Attempted to release a read lock while not holding it " + "[lock=" + U.hexLong(lock) + ", state=" + U.hexLong(state) + ']'); long updated = updateState(state, -1, 0, 0); assert updated != 0; if (GridUnsafe.compareAndSwapLong(null, lock, state, updated)) { // Notify monitor if we were CASed to zero and there is a write waiter. if (lockCount(updated) == 0 && writersWaitCount(updated) > 0) { int idx = lockIndex(lock); ReentrantLock lockObj = locks[idx]; lockObj.lock(); try { // Note that we signal all waiters for this stripe. Since not all waiters in this // stripe/index belong to this particular lock, we can't wake up just one of them. writeConditions[idx].signalAll(); } finally { lockObj.unlock(); } } return; } } }
/** * @param state State to update. * @param lockDelta Lock counter delta. * @param readersWaitDelta Readers wait delta. * @param writersWaitDelta Writers wait delta. * @return Modified state. */ private long updateState(long state, int lockDelta, int readersWaitDelta, int writersWaitDelta) { int lock = lockCount(state); int tag = tag(state); int readersWait = readersWaitCount(state); int writersWait = writersWaitCount(state); lock += lockDelta; readersWait += readersWaitDelta; writersWait += writersWaitDelta; if (readersWait > MAX_WAITERS) throw new IllegalStateException("Failed to add read waiter (too many waiting threads): " + MAX_WAITERS); if (writersWait > MAX_WAITERS) throw new IllegalStateException("Failed to add write waiter (too many waiting threads): " + MAX_WAITERS); assert readersWait >= 0 : readersWait; assert writersWait >= 0 : writersWait; assert lock >= -1; return buildState(writersWait, readersWait, tag, lock); }
/** * @param state State to update. * @return Modified state. */ private long releaseWithTag(long state, int newTag) { int lock = lockCount(state); int readersWait = readersWaitCount(state); int writersWait = writersWaitCount(state); int tag = newTag == TAG_LOCK_ALWAYS ? tag(state) : newTag & 0xFFFF; lock += 1; assert readersWait >= 0 : readersWait; assert writersWait >= 0 : writersWait; assert lock >= -1; return buildState(writersWait, readersWait, tag, lock); }
/** * @param lock Lock address. */ public void writeUnlock(long lock, int tag) { long updated; assert tag != 0; while (true) { long state = GridUnsafe.getLongVolatile(null, lock); if (lockCount(state) != -1) throw new IllegalMonitorStateException("Attempted to release write lock while not holding it " + "[lock=" + U.hexLong(lock) + ", state=" + U.hexLong(state) + ']'); updated = releaseWithTag(state, tag); assert updated != 0; if (GridUnsafe.compareAndSwapLong(null, lock, state, updated)) break; } int writeWaitCnt = writersWaitCount(updated); int readWaitCnt = readersWaitCount(updated); if (writeWaitCnt > 0 || readWaitCnt > 0) { int idx = lockIndex(lock); ReentrantLock lockObj = locks[idx]; lockObj.lock(); try { signalNextWaiter(writeWaitCnt, readWaitCnt, idx); } finally { lockObj.unlock(); } } }
/** * @param state Lock state. * @return {@code True} if no read locks are acquired. */ private boolean canWriteLock(long state) { return lockCount(state) == 0; }
/** * @param state Lock state. * @return {@code True} if write lock is not acquired. */ private boolean canReadLock(long state) { return lockCount(state) >= 0; }
/** * @param lock Lock to check. * @return {@code True} if write lock is held by any thread for the given offheap RW lock. */ public boolean isWriteLocked(long lock) { return lockCount(GridUnsafe.getLongVolatile(null, lock)) == -1; }
/** * @param lock Lock to check. * @return {@code True} if at least one read lock is held by any thread for the given offheap RW lock. */ public boolean isReadLocked(long lock) { return lockCount(GridUnsafe.getLongVolatile(null, lock)) > 0; }
/** * @param state State to update. * @param lockDelta Lock counter delta. * @param readersWaitDelta Readers wait delta. * @param writersWaitDelta Writers wait delta. * @return Modified state. */ private long updateState(long state, int lockDelta, int readersWaitDelta, int writersWaitDelta) { int lock = lockCount(state); int tag = tag(state); int readersWait = readersWaitCount(state); int writersWait = writersWaitCount(state); lock += lockDelta; readersWait += readersWaitDelta; writersWait += writersWaitDelta; if (readersWait > MAX_WAITERS) throw new IllegalStateException("Failed to add read waiter (too many waiting threads): " + MAX_WAITERS); if (writersWait > MAX_WAITERS) throw new IllegalStateException("Failed to add write waiter (too many waiting threads): " + MAX_WAITERS); assert readersWait >= 0 : readersWait; assert writersWait >= 0 : writersWait; assert lock >= -1; return buildState(writersWait, readersWait, tag, lock); }
/** * @param lock Lock address. */ public void readUnlock(long lock) { while (true) { long state = GridUnsafe.getLongVolatile(null, lock); if (lockCount(state) <= 0) throw new IllegalMonitorStateException("Attempted to release a read lock while not holding it " + "[lock=" + U.hexLong(lock) + ", state=" + U.hexLong(state) + ']'); long updated = updateState(state, -1, 0, 0); assert updated != 0; if (GridUnsafe.compareAndSwapLong(null, lock, state, updated)) { // Notify monitor if we were CASed to zero and there is a write waiter. if (lockCount(updated) == 0 && writersWaitCount(updated) > 0) { int idx = lockIndex(lock); ReentrantLock lockObj = locks[idx]; lockObj.lock(); try { // Note that we signal all waiters for this stripe. Since not all waiters in this // stripe/index belong to this particular lock, we can't wake up just one of them. writeConditions[idx].signalAll(); } finally { lockObj.unlock(); } } return; } } }
/** * @param state State to update. * @return Modified state. */ private long releaseWithTag(long state, int newTag) { int lock = lockCount(state); int readersWait = readersWaitCount(state); int writersWait = writersWaitCount(state); int tag = newTag == TAG_LOCK_ALWAYS ? tag(state) : newTag & 0xFFFF; lock += 1; assert readersWait >= 0 : readersWait; assert writersWait >= 0 : writersWait; assert lock >= -1; return buildState(writersWait, readersWait, tag, lock); }
/** * @param lock Lock address. */ public void writeUnlock(long lock, int tag) { long updated; assert tag != 0; while (true) { long state = GridUnsafe.getLongVolatile(null, lock); if (lockCount(state) != -1) throw new IllegalMonitorStateException("Attempted to release write lock while not holding it " + "[lock=" + U.hexLong(lock) + ", state=" + U.hexLong(state)); updated = releaseWithTag(state, tag); assert updated != 0; if (GridUnsafe.compareAndSwapLong(null, lock, state, updated)) break; } int writeWaitCnt = writersWaitCount(updated); int readWaitCnt = readersWaitCount(updated); if (writeWaitCnt > 0 || readWaitCnt > 0) { int idx = lockIndex(lock); ReentrantLock lockObj = locks[idx]; lockObj.lock(); try { signalNextWaiter(writeWaitCnt, readWaitCnt, idx); } finally { lockObj.unlock(); } } }