177 |
|
* read-locked. The read count is ignored when validating |
178 |
|
* "optimistic" seqlock-reader-style stamps. Because we must use |
179 |
|
* a small finite number of bits (currently 7) for readers, a |
180 |
< |
* supplementatry reader overflow word is used when then number of |
180 |
> |
* supplementary reader overflow word is used when then number of |
181 |
|
* readers exceeds the count field. We do this by treating the max |
182 |
|
* reader count value (RBITS) as a spinlock protecting overflow |
183 |
|
* updates. |
235 |
|
private static final int NCPU = Runtime.getRuntime().availableProcessors(); |
236 |
|
|
237 |
|
/** Maximum number of retries before blocking on acquisition */ |
238 |
< |
private static final int SPINS = NCPU > 1 ? 1 << 6 : 1; |
238 |
> |
private static final int SPINS = (NCPU > 1) ? 1 << 6 : 1; |
239 |
|
|
240 |
|
/** Maximum number of retries before re-blocking on write lock */ |
241 |
< |
private static final int MAX_HEAD_SPINS = NCPU > 1 ? 1 << 12 : 1; |
241 |
> |
private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 12 : 1; |
242 |
|
|
243 |
|
/** The period for yielding when waiting for overflow spinlock */ |
244 |
|
private static final int OVERFLOW_YIELD_RATE = 7; // must be power 2 - 1 |
303 |
|
* Exclusively acquires the lock, blocking if necessary |
304 |
|
* until available. |
305 |
|
* |
306 |
< |
* @return a stamp that can be used to unlock or convert mode. |
306 |
> |
* @return a stamp that can be used to unlock or convert mode |
307 |
|
*/ |
308 |
|
public long writeLock() { |
309 |
|
long s, next; |
329 |
|
|
330 |
|
/** |
331 |
|
* Exclusively acquires the lock if it is available within the |
332 |
< |
* given time and the current thread has not been interrupted |
332 |
> |
* given time and the current thread has not been interrupted. |
333 |
|
* |
334 |
|
* @return a stamp that can be used to unlock or convert mode, |
335 |
< |
* or zero if the lock is not available. |
335 |
> |
* or zero if the lock is not available |
336 |
|
* @throws InterruptedException if the current thread is interrupted |
337 |
< |
* before acquiring the lock. |
337 |
> |
* before acquiring the lock |
338 |
|
*/ |
339 |
|
public long tryWriteLock(long time, TimeUnit unit) |
340 |
|
throws InterruptedException { |
341 |
< |
long nanos = unit.toNanos(time); |
341 |
> |
long nanos = unit.toNanos(time); |
342 |
|
if (!Thread.interrupted()) { |
343 |
|
long s, next, deadline; |
344 |
|
if (((s = state) & ABITS) == 0L && |
358 |
|
* Exclusively acquires the lock, blocking if necessary |
359 |
|
* until available or the current thread is interrupted. |
360 |
|
* |
361 |
< |
* @return a stamp that can be used to unlock or convert mode. |
361 |
> |
* @return a stamp that can be used to unlock or convert mode |
362 |
|
* @throws InterruptedException if the current thread is interrupted |
363 |
< |
* before acquiring the lock. |
363 |
> |
* before acquiring the lock |
364 |
|
*/ |
365 |
|
public long writeLockInterruptibly() throws InterruptedException { |
366 |
|
if (!Thread.interrupted()) { |
378 |
|
* Non-exclusively acquires the lock, blocking if necessary |
379 |
|
* until available. |
380 |
|
* |
381 |
< |
* @return a stamp that can be used to unlock or convert mode. |
381 |
> |
* @return a stamp that can be used to unlock or convert mode |
382 |
|
*/ |
383 |
|
public long readLock() { |
384 |
|
for (;;) { |
401 |
|
* Non-exclusively acquires the lock if it is immediately available. |
402 |
|
* |
403 |
|
* @return a stamp that can be used to unlock or convert mode, |
404 |
< |
* or zero if the lock is not available. |
404 |
> |
* or zero if the lock is not available |
405 |
|
*/ |
406 |
|
public long tryReadLock() { |
407 |
|
for (;;) { |
419 |
|
|
420 |
|
/** |
421 |
|
* Non-exclusively acquires the lock if it is available within the |
422 |
< |
* given time and the current thread has not been interrupted |
422 |
> |
* given time and the current thread has not been interrupted. |
423 |
|
* |
424 |
|
* @return a stamp that can be used to unlock or convert mode, |
425 |
< |
* or zero if the lock is not available. |
425 |
> |
* or zero if the lock is not available |
426 |
|
* @throws InterruptedException if the current thread is interrupted |
427 |
< |
* before acquiring the lock. |
427 |
> |
* before acquiring the lock |
428 |
|
*/ |
429 |
|
public long tryReadLock(long time, TimeUnit unit) |
430 |
|
throws InterruptedException { |
457 |
|
* Non-exclusively acquires the lock, blocking if necessary |
458 |
|
* until available or the current thread is interrupted. |
459 |
|
* |
460 |
< |
* @return a stamp that can be used to unlock or convert mode. |
460 |
> |
* @return a stamp that can be used to unlock or convert mode |
461 |
|
* @throws InterruptedException if the current thread is interrupted |
462 |
< |
* before acquiring the lock. |
462 |
> |
* before acquiring the lock |
463 |
|
*/ |
464 |
|
public long readLockInterruptibly() throws InterruptedException { |
465 |
|
if (!Thread.interrupted()) { |
512 |
|
* |
513 |
|
* @param stamp a stamp returned by a write-lock operation |
514 |
|
* @throws IllegalMonitorStateException if the stamp does |
515 |
< |
* not match the current state of this lock. |
515 |
> |
* not match the current state of this lock |
516 |
|
*/ |
517 |
|
public void unlockWrite(long stamp) { |
518 |
|
if (state != stamp || (stamp & WBIT) == 0L) |
527 |
|
* |
528 |
|
* @param stamp a stamp returned by a read-lock operation |
529 |
|
* @throws IllegalMonitorStateException if the stamp does |
530 |
< |
* not match the current state of this lock. |
530 |
> |
* not match the current state of this lock |
531 |
|
*/ |
532 |
|
public void unlockRead(long stamp) { |
533 |
|
long s, m; |
557 |
|
* |
558 |
|
* @param stamp a stamp returned by a lock operation |
559 |
|
* @throws IllegalMonitorStateException if the stamp does |
560 |
< |
* not match the current state of this lock. |
560 |
> |
* not match the current state of this lock |
561 |
|
*/ |
562 |
|
public void unlock(long stamp) { |
563 |
|
long a = stamp & ABITS, m, s; |
673 |
|
*/ |
674 |
|
public long tryConvertToOptimisticRead(long stamp) { |
675 |
|
long a = stamp & ABITS, m, s, next; |
676 |
< |
while (((s = U.getLongVolatile(this, STATE)) & |
676 |
> |
while (((s = U.getLongVolatile(this, STATE)) & |
677 |
|
SBITS) == (stamp & SBITS)) { |
678 |
|
if ((m = s & ABITS) == 0L) { |
679 |
|
if (a != 0L) |
707 |
|
* stamp value. This method may be useful for recovery after |
708 |
|
* errors. |
709 |
|
* |
710 |
< |
* @return true if the lock was held, else false. |
710 |
> |
* @return true if the lock was held, else false |
711 |
|
*/ |
712 |
|
public boolean tryUnlockWrite() { |
713 |
|
long s; |
724 |
|
* requiring a stamp value. This method may be useful for recovery |
725 |
|
* after errors. |
726 |
|
* |
727 |
< |
* @return true if the read lock was held, else false. |
727 |
> |
* @return true if the read lock was held, else false |
728 |
|
*/ |
729 |
|
public boolean tryUnlockRead() { |
730 |
|
long s, m; |
773 |
|
* Tries to increment readerOverflow by first setting state |
774 |
|
* access bits value to RBITS, indicating hold of spinlock, |
775 |
|
* then updating, then releasing. |
776 |
+ |
* |
777 |
|
* @param stamp, assumed that (stamp & ABITS) >= RFULL |
778 |
|
* @return new stamp on success, else zero |
779 |
|
*/ |
785 |
|
return s; |
786 |
|
} |
787 |
|
} |
788 |
< |
else if ((ThreadLocalRandom.current().nextInt() & |
788 |
> |
else if ((ThreadLocalRandom.current().nextInt() & |
789 |
|
OVERFLOW_YIELD_RATE) == 0) |
790 |
|
Thread.yield(); |
791 |
|
return 0L; |
793 |
|
|
794 |
|
/** |
795 |
|
* Tries to decrement readerOverflow. |
796 |
+ |
* |
797 |
|
* @param stamp, assumed that (stamp & ABITS) >= RFULL |
798 |
|
* @return new stamp on success, else zero |
799 |
|
*/ |
811 |
|
return next; |
812 |
|
} |
813 |
|
} |
814 |
< |
else if ((ThreadLocalRandom.current().nextInt() & |
814 |
> |
else if ((ThreadLocalRandom.current().nextInt() & |
815 |
|
OVERFLOW_YIELD_RATE) == 0) |
816 |
|
Thread.yield(); |
817 |
|
return 0L; |
913 |
|
|
914 |
|
/** |
915 |
|
* Possibly spins trying to obtain write lock, then enqueues and |
916 |
< |
* blocks while not head of write queue or cannot aquire lock, |
916 |
> |
* blocks while not head of write queue or cannot acquire lock, |
917 |
|
* possibly spinning when at head; cancelling on timeout or |
918 |
|
* interrupt. |
919 |
|
* |
920 |
|
* @param interruptible true if should check interrupts and if so |
921 |
|
* return INTERRUPTED |
922 |
|
* @param deadline if nonzero, the System.nanoTime value to timeout |
923 |
< |
* at (and return zero). |
923 |
> |
* at (and return zero) |
924 |
|
*/ |
925 |
|
private long awaitWrite(boolean interruptible, long deadline) { |
926 |
|
WNode node = null; |
1021 |
|
} |
1022 |
|
} |
1023 |
|
writerPrefSignal(); |
1024 |
< |
return (interrupted || Thread.interrupted())? INTERRUPTED : 0L; |
1024 |
> |
return (interrupted || Thread.interrupted()) ? INTERRUPTED : 0L; |
1025 |
|
} |
1026 |
|
|
1027 |
< |
/* |
1027 |
> |
/** |
1028 |
|
* Waits for read lock or timeout or interrupt. The form of |
1029 |
|
* awaitRead differs from awaitWrite mainly because it must |
1030 |
|
* restart (with a new wait node) if the thread was unqueued and |
1129 |
|
} |
1130 |
|
} |
1131 |
|
readerPrefSignal(); |
1132 |
< |
return (interrupted || Thread.interrupted())? INTERRUPTED : 0L; |
1132 |
> |
return (interrupted || Thread.interrupted()) ? INTERRUPTED : 0L; |
1133 |
|
} |
1134 |
|
|
1135 |
|
// Unsafe mechanics |
1203 |
|
} |
1204 |
|
|
1205 |
|
} |
1204 |
– |
|