3. public final class RequestCreateAvatar {
private final String avatarName;
}
S
private final Character character;
R
void createAvatar(String avatarName, Character character) {
MsgRequest
sendCmd(new RequestCreateAvatar(avatarName, character));
Async<Void> createAvatar(String avatarName, Character character) {
}
CreateAvatarResult result = call(avatarManager.createAvatar(
avatarName, characterfinal class CreateAvatarHandler {
public
)); RequestHandler()
public void handle(RequestCreateAvatar msg) {
sendMsgToClient(result); CreateAvatarResult result = avatarManager.createAvatar(msg);
sendMsg(new ResponseCreateAvatar(result));
MsgResponse
return nothing(); }
} }
public final class CreateAvatarResponseHandler {
public void handle(ResponseCreateAvatar msg) {
sendMsgToClient(msg); ResponseHandler()
}
}
4.
5. Причины
• Хочется писать простой линейный Java-код
• ОС-потоки слишком накладны
• Требуется сохранить однопоточный дизайн
6. С высоты птичьего полёта
Инструментатор Планировщик
Рантайм Инспекции
16. Инструментирование (4)
...
case 42
... Context r = new bar_Context();
x = call(bar()); c.pushCall(r);
...
return 43;
case 43:
c.x = (String) c.takeResult();
...
17. Инструментирование (5)
• Директивы, ссылающиеся на исходный файл,
вставляются инструментатором в
сгенерированный метод
• Это позволяет использовать пошаговую
отладку
• Ограничение: нельзя с помощью Step Over
перейти через точку разрыва
18. Исключения
• Рантайм ловит все исключения, вылетевшие из
Async-метода
• Исключение заворачивается в служебный объект
• При запросе результата вызывающим Async-
методом исключение выбрасывается заново
• Если исключение вылетает за пределы файбера, то
это диагностируется как ошибка
19. Прерывание файбера
• В каждой точке входа в Async-метод
проверяется, не был ли прерван текущий
файбер
• Если файбер был прерван, то
выбрасывается служебное исключение
FiberInterruptedException
21. Гарантии FiberManager
• Файберы должны исполняться в порядке
добавления и возобновления
• Приостановленные файберы не должны
исполняться
22. Thread safety
• Методы scheduleFiber() и resumeFiber()
могут выполняться из любого потока
• Все остальные методы – только из потока, к
которому привязан планировщик
• На каждый поток есть свой планировщик
23. StackTrace (1)
• Stack trace из new Throwable().getStackTrace() не
достаточен
• Программист хочет видеть:
– стек Async-методов
– стек в момент порождения файбера
• Файбер может быть создан внутри другого файбера
• Stack trace должен разрешаться (resolve) только
тогда, когда он реально необходим
24. StackTrace (2)
• Рантайм получает уже готовое исключение
• К этому исключению нужно добавить
– стек файбера
– стек момента порождения файбера
• Используется addSuppressed()
25. StackTrace (3)
• Переопределяется метод fillInStackTrace(),
чтобы не собирать обычный stack trace
• Массив StackTraceElement[] формируется
только по запросу getCause() и при
сериализации
26. java.lang.Throwable
at asserts.Verify.fail(Verify.java:47)
at gm.cc.c.t.CmdTeleportRandomByMapType.asyncRun$Async(CmdTeleportRandomByMapType.jav
at gm.cc.c.t.CmdTeleportRandomByMapType$Context_asyncRun_LmsgSystem#locales#Abonent_.
at f.i.AsyncImpl.updateSafe(AsyncImpl.java:37)
at f.i.FiberImpl.updateInternal(FiberImpl.java:154)
at f.i.FiberImpl.update(FiberImpl.java:130)
at f.i.FiberManagerAbstract.updateFiber(FiberManagerAbstract.java:297)
...
at java.lang.Thread.run(Thread.java:722)
Suppressed: f.i.FiberStackTraceHolderException: Fiber stack trace
Caused by: f.i.FiberStackTraceHolderException$Helper
at asserts.Verify.fail(Verify.java:47)
at gm.cc.c.t.CmdTeleportRandomByMapType.asyncRun(CmdTeleportRandomByMapType.java
at ms.l.AsyncMsg.run(AsyncMsg.java:37)
at ms.i.mp.ServerMsgPublisher.processMsg(ServerMsgPublisher.java:331)
at ms.i.mp.ServerMsgPublisher.addMsgFast(ServerMsgPublisher.java:118)
...
at java.lang.Thread.run(Thread.java:722)
27. Узкие места (1)
• Инструментатор меняет сигнатуру метода
• Служебные методы call() и result() вырезаются,
чтобы байткод соответствовал новой сигнатуре
• Об этом не догадывается IntelliJ Idea, которая
вставляет проверки на != null
• Инструментатор вырезает такие проверки из
Async-методов
28. Узкие места (2)
• Если Async-метод декларирует throws
SomeUncheckedException
– синтаксис java потребует его обработки
– catch-блок для этого исключения никогда не будет
вызван
– исключение пролетит в рантайм, т. к. для него нет
соответствующего catch
29. Узкие места (3)
• Синтаксис не запрещает вызов Async-
метода из обычного
• Вызываемый метод не исполнится
30. Узкие места (4)
• Точки разрыва не могут быть в блоке finally
• Причина: в этом случае исключение может
быть проигнорировано