547 * <ul>
548 * <li>has its interrupted status set on entry to this method; or
549 * <li>is {@linkplain Thread#interrupt interrupted} while waiting
550 * for the exchange,
551 * </ul>
552 * then {@link InterruptedException} is thrown and the current thread's
553 * interrupted status is cleared.
554 *
555 * @param x the object to exchange
556 * @return the object provided by the other thread
557 * @throws InterruptedException if the current thread was
558 * interrupted while waiting
559 */
560 @SuppressWarnings("unchecked")
561 public V exchange(V x) throws InterruptedException {
562 Object v;
563 Node[] a;
564 Object item = (x == null) ? NULL_ITEM : x; // translate null args
565 if (((a = arena) != null ||
566 (v = slotExchange(item, false, 0L)) == null) &&
567 ((Thread.interrupted() || // disambiguates null return
568 (v = arenaExchange(item, false, 0L)) == null)))
569 throw new InterruptedException();
570 return (v == NULL_ITEM) ? null : (V)v;
571 }
572
573 /**
574 * Waits for another thread to arrive at this exchange point (unless
575 * the current thread is {@linkplain Thread#interrupt interrupted} or
576 * the specified waiting time elapses), and then transfers the given
577 * object to it, receiving its object in return.
578 *
579 * <p>If another thread is already waiting at the exchange point then
580 * it is resumed for thread scheduling purposes and receives the object
581 * passed in by the current thread. The current thread returns immediately,
582 * receiving the object passed to the exchange by that other thread.
583 *
584 * <p>If no other thread is already waiting at the exchange then the
585 * current thread is disabled for thread scheduling purposes and lies
586 * dormant until one of three things happens:
587 * <ul>
588 * <li>Some other thread enters the exchange; or
603 * TimeoutException} is thrown. If the time is less than or equal
604 * to zero, the method will not wait at all.
605 *
606 * @param x the object to exchange
607 * @param timeout the maximum time to wait
608 * @param unit the time unit of the {@code timeout} argument
609 * @return the object provided by the other thread
610 * @throws InterruptedException if the current thread was
611 * interrupted while waiting
612 * @throws TimeoutException if the specified waiting time elapses
613 * before another thread enters the exchange
614 */
615 @SuppressWarnings("unchecked")
616 public V exchange(V x, long timeout, TimeUnit unit)
617 throws InterruptedException, TimeoutException {
618 Object v;
619 Object item = (x == null) ? NULL_ITEM : x;
620 long ns = unit.toNanos(timeout);
621 if ((arena != null ||
622 (v = slotExchange(item, true, ns)) == null) &&
623 ((Thread.interrupted() ||
624 (v = arenaExchange(item, true, ns)) == null)))
625 throw new InterruptedException();
626 if (v == TIMED_OUT)
627 throw new TimeoutException();
628 return (v == NULL_ITEM) ? null : (V)v;
629 }
630
631 // VarHandle mechanics
632 private static final VarHandle BOUND;
633 private static final VarHandle SLOT;
634 private static final VarHandle MATCH;
635 private static final VarHandle AA;
636 static {
637 try {
638 MethodHandles.Lookup l = MethodHandles.lookup();
639 BOUND = l.findVarHandle(Exchanger.class, "bound", int.class);
640 SLOT = l.findVarHandle(Exchanger.class, "slot", Node.class);
641 MATCH = l.findVarHandle(Node.class, "match", Object.class);
642 AA = MethodHandles.arrayElementVarHandle(Node[].class);
643 } catch (ReflectiveOperationException e) {
644 throw new ExceptionInInitializerError(e);
|
547 * <ul>
548 * <li>has its interrupted status set on entry to this method; or
549 * <li>is {@linkplain Thread#interrupt interrupted} while waiting
550 * for the exchange,
551 * </ul>
552 * then {@link InterruptedException} is thrown and the current thread's
553 * interrupted status is cleared.
554 *
555 * @param x the object to exchange
556 * @return the object provided by the other thread
557 * @throws InterruptedException if the current thread was
558 * interrupted while waiting
559 */
560 @SuppressWarnings("unchecked")
561 public V exchange(V x) throws InterruptedException {
562 Object v;
563 Node[] a;
564 Object item = (x == null) ? NULL_ITEM : x; // translate null args
565 if (((a = arena) != null ||
566 (v = slotExchange(item, false, 0L)) == null) &&
567 (Thread.interrupted() || // disambiguates null return
568 (v = arenaExchange(item, false, 0L)) == null))
569 throw new InterruptedException();
570 return (v == NULL_ITEM) ? null : (V)v;
571 }
572
573 /**
574 * Waits for another thread to arrive at this exchange point (unless
575 * the current thread is {@linkplain Thread#interrupt interrupted} or
576 * the specified waiting time elapses), and then transfers the given
577 * object to it, receiving its object in return.
578 *
579 * <p>If another thread is already waiting at the exchange point then
580 * it is resumed for thread scheduling purposes and receives the object
581 * passed in by the current thread. The current thread returns immediately,
582 * receiving the object passed to the exchange by that other thread.
583 *
584 * <p>If no other thread is already waiting at the exchange then the
585 * current thread is disabled for thread scheduling purposes and lies
586 * dormant until one of three things happens:
587 * <ul>
588 * <li>Some other thread enters the exchange; or
603 * TimeoutException} is thrown. If the time is less than or equal
604 * to zero, the method will not wait at all.
605 *
606 * @param x the object to exchange
607 * @param timeout the maximum time to wait
608 * @param unit the time unit of the {@code timeout} argument
609 * @return the object provided by the other thread
610 * @throws InterruptedException if the current thread was
611 * interrupted while waiting
612 * @throws TimeoutException if the specified waiting time elapses
613 * before another thread enters the exchange
614 */
615 @SuppressWarnings("unchecked")
616 public V exchange(V x, long timeout, TimeUnit unit)
617 throws InterruptedException, TimeoutException {
618 Object v;
619 Object item = (x == null) ? NULL_ITEM : x;
620 long ns = unit.toNanos(timeout);
621 if ((arena != null ||
622 (v = slotExchange(item, true, ns)) == null) &&
623 (Thread.interrupted() ||
624 (v = arenaExchange(item, true, ns)) == null))
625 throw new InterruptedException();
626 if (v == TIMED_OUT)
627 throw new TimeoutException();
628 return (v == NULL_ITEM) ? null : (V)v;
629 }
630
631 // VarHandle mechanics
632 private static final VarHandle BOUND;
633 private static final VarHandle SLOT;
634 private static final VarHandle MATCH;
635 private static final VarHandle AA;
636 static {
637 try {
638 MethodHandles.Lookup l = MethodHandles.lookup();
639 BOUND = l.findVarHandle(Exchanger.class, "bound", int.class);
640 SLOT = l.findVarHandle(Exchanger.class, "slot", Node.class);
641 MATCH = l.findVarHandle(Node.class, "match", Object.class);
642 AA = MethodHandles.arrayElementVarHandle(Node[].class);
643 } catch (ReflectiveOperationException e) {
644 throw new ExceptionInInitializerError(e);
|