Класс SwitchPoint

public class SwitchPoint
extends Object

Объект, который может публиковать переходы состояния другим потокам. Точка переключения изначально находится в состоянии действительно, но может быть в любое время изменена на состояние недействительно. Отмена инвалидации невозможна. Точка переключения может объединить защищённую пару обработчиков методов в защищённого делегата. Защищённый делегат — это обработчик методов, который делегирует одному из старых обработчиков методов. Состояние точки переключения определяет, какой из двух получает делегирование.

Единая точка переключения может использоваться для управления любым количеством обработчиков методов. (Косвенно, следовательно, она может управлять любым количеством мест вызова.) Это делается путём использования единой точки переключения в качестве фабрики для объединения любого числа пар защищённых обработчиков методов в защищённые делегаты.

Когда защищённый делегат создаётся из защищённой пары, пара оборачивается в новый обработчик методов M, который постоянно ассоциируется с точкой переключения, которая его создала. Каждая пара состоит из целевого T и запасного F. Пока точка переключения действительна, вызовы к M делегируются T. После ее инвалидации вызовы делегируются F.

Инвалидация глобальна и мгновенна, как если бы точка переключения содержала переменную volatile boolean, которая консультируется при каждом вызове M. Инвалидация также постоянна, что означает, что точка переключения может изменить состояние только один раз. Точка переключения всегда будет делегировать F после инвалидации. В этот момент guardWithTest может игнорировать T и возвращать F.

Вот пример точки переключения в действии:

MethodHandle MH_strcat = MethodHandles.lookup()
     .findVirtual(String.class, "concat", MethodType.methodType(String.class, String.class));
 SwitchPoint spt = new SwitchPoint();
 assert(!spt.hasBeenInvalidated());
 // the following steps may be repeated to re-use the same switch point:
 MethodHandle worker1 = MH_strcat;
 MethodHandle worker2 = MethodHandles.permuteArguments(MH_strcat, MH_strcat.type(), 1, 0);
 MethodHandle worker = spt.guardWithTest(worker1, worker2);
 assertEquals("method", (String) worker.invokeExact("met", "hod"));
 SwitchPoint.invalidateAll(new SwitchPoint[]{ spt });
 assert(spt.hasBeenInvalidated());
 assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));

Обсуждение: Точки переключения полезны без наследования. Их также можно наследоваться. Это может быть полезно для того, чтобы связать логику инвалидации, специфичную для приложения, с точкой переключения. Обратите внимание, что нет постоянной связи между точкой переключения и обработчиками методов, которые она производит и потребляет. Сборщик мусора может собирать обработчики методов, произведённые или потреблённые точкой переключения, независимо от срока службы самой точки переключения.

Примечание по реализации: Точка переключения работает так, как если бы она была реализована поверх MutableCallSite, приблизительно следующим образом:

public class SwitchPoint {
     private static final MethodHandle
         K_true  = MethodHandles.constant(boolean.class, true),
         K_false = MethodHandles.constant(boolean.class, false);
     private final MutableCallSite mcs;
     private final MethodHandle mcsInvoker;
     public SwitchPoint() {
         this.mcs = new MutableCallSite(K_true);
         this.mcsInvoker = mcs.dynamicInvoker();
     }
     public MethodHandle guardWithTest(
             MethodHandle target, MethodHandle fallback) {
         // Note:  mcsInvoker is of type ()boolean.
         // Target and fallback may take any arguments, but must have the same type.
         return MethodHandles.guardWithTest(this.mcsInvoker, target, fallback);
     }
     public static void invalidateAll(SwitchPoint[] spts) {
         List<MutableCallSite> mcss = new ArrayList<>();
         for (SwitchPoint spt : spts)  mcss.add(spt.mcs);
         for (MutableCallSite mcs : mcss)  mcs.setTarget(K_false);
         MutableCallSite.syncAll(mcss.toArray(new MutableCallSite[0]));
     }
 }
С тех пор:
1.7

Конструкторы

Конструктор Описание
SwitchPoint()

Создаёт новую точку переключения.

Методы

Модификатор и тип Метод Описание
MethodHandle guardWithTest​(MethodHandle target, MethodHandle fallback)

Возвращает обработчик методов, который всегда делегирует либо цели, либо резервному.

boolean hasBeenInvalidated()

Определяет, была ли эта точка переключения уже инвалидирована.

static void invalidateAll​(SwitchPoint[] switchPoints)

Устанавливает все заданные точки переключения в состояние недействительности.

Методы, объявленные в классе java.lang.Object

clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Подробное описание конструкторов

SwitchPoint

public SwitchPoint()

Создаёт новую точку переключения.

Подробное описание методов

hasBeenInvalidated

public boolean hasBeenInvalidated()

Определяет, была ли эта точка переключения уже инвалидирована.

Обсуждение: Из-за однонаправленного характера инвалидации, после того, как точка переключения начнёт возвращать true для hasBeenInvalidated, она всегда будет возвращать true в будущем. С другой стороны, действительная точка переключения, видимая другим потокам, может быть инвалидирована в любой момент из-за запроса другого потока.

Поскольку инвалидация — это глобальная и мгновенная операция, выполнение этого запроса в действительной точке переключения должно быть внутренне упорядочено с любыми другими потоками, которые могут вызвать инвалидацию. Поэтому этот запрос может быть дорогостоящим. Рекомендуемый способ построения обработчика методов типа boolean, который запрашивает состояние инвалидации точки переключения s состоит в вызове s.guardWithTest на constant true и false обработчиков методов.

Возвращает:
true, если эта точка переключения была инвалидирована

guardWithTest

public MethodHandle guardWithTest(MethodHandle target,
                                  MethodHandle fallback)

Возвращает обработчик методов, который всегда делегирует либо цели, либо резервному. Обработчик методов будет делегировать цели ровно до тех пор, пока точка переключения действительна. После этого он будет постоянно делегировать резервному.

Цель и резервный должны быть ровно одного типа метода, и результирующий объединённый обработчик методов также будет этого типа.

Параметры:
target - обработчик методов, выбранный точкой переключения, пока она действительна
fallback - обработчик методов, выбранный точкой переключения после её инвалидации
Возвращает:
объединённый обработчик методов, который всегда вызывает либо цель, либо резервный
Исключения:
NullPointerException - если любой из аргументов равен null
IllegalArgumentException - если два типа методов не совпадают
См. также:
MethodHandles.guardWithTest(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle)

invalidateAll

public static void invalidateAll(SwitchPoint[] switchPoints)

Устанавливает все заданные точки переключения в состояние недействительности. После выполнения этого вызова ни один поток не увидит ни одну из точек переключения в состоянии действительности.

Эта операция может быть дорогостоящей и должна использоваться с осторожностью. Если возможно, она должна быть буферизована для пакетной обработки набора точек переключения.

Если switchPoints содержит элемент null, будет выброшено NullPointerException. В этом случае некоторые ненулевые элементы в массиве могут быть обработаны до того, как метод вернётся аномально. Какие именно элементы (если таковые имеются) зависят от реализации.

Обсуждение: Из соображений производительности invalidateAll не является виртуальным методом на одной точке переключения, а относится к набору точек переключения. Некоторые реализации могут понести значительные фиксированные накладные расходы при обработке одной или нескольких операций инвалидации, но небольшие дополнительные накладные расходы для каждой дополнительной операции инвалидации. В любом случае эта операция, скорее всего, будет дорогостоящей, так как другим потокам может потребоваться каким-то образом прервать их, чтобы они заметили обновлённое состояние точки переключения. Тем не менее, можно заметить, что один вызов для инвалидации нескольких точек переключения имеет тот же формальный эффект, что и много вызовов, каждый из которых только на одной из точек переключения.

Примечание по реализации: Простые реализации SwitchPoint могут использовать частный MutableCallSite для публикации состояния точки переключения. В такой реализации метод invalidateAll может просто изменить цель места вызова и выполнить один вызов синхронизации всех частных мест вызова.

Параметры:
switchPoints - массив мест вызова, которые нужно синхронизировать
Исключения:
NullPointerException - если ссылка на массив switchPoints равна null или массив содержит null

© 1993, 2020, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/invoke/SwitchPoint.html

Spec-Zone .ru
спецификации, руководства, описания, API