Size: a a a

2019 October 18

VS

Vladimir Sitnikov in Kotlin Moscow
вызывать suspend’ы из Java я умею. Мне хочется научиться реализовыывать suspend функции на Java
источник

SM

Sergey Morgunov in Kotlin Moscow
Значит я правильно всё-таки понял задачу 🙂
источник

AN

Alexander Nozik in Kotlin Moscow
Vladimir Sitnikov
вызывать suspend’ы из Java я умею. Мне хочется научиться реализовыывать suspend функции на Java
Это бессмысленная идея, поскольку весь смысл суспендов в том, что компилятор генерит суспешен поинты. В джаве руками их генерить очень тяжко. А почему бы просто функцию не сделать? Обычную без суспеншен поинтов?
источник

SM

Sergey Morgunov in Kotlin Moscow
Alexander Nozik
Это бессмысленная идея, поскольку весь смысл суспендов в том, что компилятор генерит суспешен поинты. В джаве руками их генерить очень тяжко. А почему бы просто функцию не сделать? Обычную без суспеншен поинтов?
Мне кажется 2 раза переписывать видимо придётся.
1. Пишем функция с Java фьючей, спокойно имплементим и используем её из Kotlin
2. Потом идём и переписываем всё на Kotlin меняя все фьючер-функции на suspend
источник

VS

Vladimir Sitnikov in Kotlin Moscow
Alexander Nozik
Это бессмысленная идея, поскольку весь смысл суспендов в том, что компилятор генерит суспешен поинты. В джаве руками их генерить очень тяжко. А почему бы просто функцию не сделать? Обычную без суспеншен поинтов?
Если всего пара suspension мест, то я и руками напишу, нет?
источник

AN

Alexander Nozik in Kotlin Moscow
Vladimir Sitnikov
Если всего пара suspension мест, то я и руками напишу, нет?
Если всего пара мест, почему не написать на котлин сразу?
источник

VS

Vladimir Sitnikov in Kotlin Moscow
Так я не новый код пишу, а внедряю suspend в сжатые сроки.
источник

VS

Vladimir Sitnikov in Kotlin Moscow
Допустим, хочу http клиент переписать на suspend. Но весь стек вызовов до http клиента должен быть suspend.
источник

Ⓢⓔⓡⓖ in Kotlin Moscow
Vladimir Sitnikov
Допустим, хочу http клиент переписать на suspend. Но весь стек вызовов до http клиента должен быть suspend.
А что ты ожидаешь от внедрения suspend?
источник

Ⓢⓔⓡⓖ in Kotlin Moscow
Как пользователь ощутит это изменение?
источник

VS

Vladimir Sitnikov in Kotlin Moscow
Cудя по всему, на этом моменте «образцовая реализация suspend функции вручную»:  https://youtu.be/UzzH4biTEbY?t=1646

Т.е. точно так же можно и на Java написать.
Но, возможно, действительно проще все классы по стектрейсу сконвертировать в Kotlin.
источник

Ⓢⓔⓡⓖ in Kotlin Moscow
@vladimirsitnikv по-возможности, ответь плз на последние 2 вопроса. Меня часто бизнес-пользователи спрашивают об этом
источник

SM

Sergey Morgunov in Kotlin Moscow
Ⓢⓔⓡⓖ
@vladimirsitnikv по-возможности, ответь плз на последние 2 вопроса. Меня часто бизнес-пользователи спрашивают об этом
Серёж, а кого ты подразумеваешь под бизнес-пользователями JMeter?
источник

I

Ilmir in Kotlin Moscow
Vladimir Sitnikov
Cудя по всему, на этом моменте «образцовая реализация suspend функции вручную»:  https://youtu.be/UzzH4biTEbY?t=1646

Т.е. точно так же можно и на Java написать.
Но, возможно, действительно проще все классы по стектрейсу сконвертировать в Kotlin.
Там нет обработки ошибок, все suspend функции возвращают Unit, нет локальных переменных, которые надо пихать в поля...
Но как-то раз я написал suspend функцию на джаве:
import kotlin.ResultKt;
import kotlin.Unit;
import kotlin.coroutines.Continuation;
import kotlin.coroutines.CoroutineContext;
import kotlin.coroutines.EmptyCoroutineContext;
import kotlin.coroutines.intrinsics.IntrinsicsKt;
import kotlin.jvm.functions.Function2;
import kotlin.reflect.KFunction;
import kotlin.reflect.full.KCallables;
import kotlin.reflect.jvm.ReflectJvmMapping;
import kotlinx.coroutines.CoroutineScope;
import kotlinx.coroutines.GlobalScope;
import kotlinx.coroutines.reactor.MonoKt;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

public class A {
   static Object invokeHandlerMethod(Method method, Object bean, Object... args) {
       KFunction<?> function = Objects.requireNonNull(ReflectJvmMapping.getKotlinFunction(method));
       if (function.isSuspend()) {
           InvokeHandleMethodContinuation lambda = new InvokeHandleMethodContinuation(function, bean, args);
           return MonoKt.mono(GlobalScope.INSTANCE, EmptyCoroutineContext.INSTANCE, lambda)
                   .onErrorMap(InvocationTargetException.class, InvocationTargetException::getTargetException);
       } else {
           List<Object> newArgs = new ArrayList<>();
           newArgs.add(bean);
           newArgs.addAll(Arrays.asList(args));
           return function.call(newArgs.toArray());
       }
   }
}

class InvokeHandleMethodContinuation implements Continuation<Object>, Function2<CoroutineScope, Continuation<?>, Object> {
   /* Continuation of caller coroutine */
   private Continuation<?> completion;
   /* state-machine label */
   int label = 0;
   /* 'captured' variables */
   final KFunction<?> function;
   final Object bean;
   final Object[] args;
   /* locals, which should be preserved between suspensions */
   /* as demonstration, I save all parameters and 'newArgs' */
   CoroutineScope scope;
   List<Object> newArgs;

   InvokeHandleMethodContinuation(KFunction<?> function, Object bean, Object[] args) {
       this.function = function;
       this.bean = bean;
       this.args = args;
   }
   
   @NotNull
   @Override
   public CoroutineContext getContext() {
       return completion.getContext();
   }
источник

I

Ilmir in Kotlin Moscow
Vladimir Sitnikov
Cудя по всему, на этом моменте «образцовая реализация suspend функции вручную»:  https://youtu.be/UzzH4biTEbY?t=1646

Т.е. точно так же можно и на Java написать.
Но, возможно, действительно проще все классы по стектрейсу сконвертировать в Kotlin.


   @Override
   public void resumeWith(@NotNull Object result) {
       try {
           Object outcome = invokeSuspend(result);
           // the coroutine is suspended. Since 'resumeWith' is called on suspended coroutines and its parent is
           // also suspended, there is no need to suspend it one more time.
           if (outcome == IntrinsicsKt.getCOROUTINE_SUSPENDED()) return;
           // coroutine has finished, wake up its parent.
           completion.resumeWith(outcome);
       } catch (Throwable e) {
           completion.resumeWith(ResultKt.createFailure(e));
       }
   }

   // It is easier to keep track of everything if the state-machine itself is in separate method of continuation, even for suspend functions.
   // The body of suspend function will be just 'new ContinuationObject(captured variables).invoke(parameters, including completion)'
   // BTW, Kotlin/Native and Kotlin/JS implement coroutines exactly this way.
   private Object invokeSuspend(@NotNull Object result) {
       // Check if we resumed with exception
       ResultKt.throwOnFailure(result);
       // State-machine itself
       // For each suspend call there should be exactly one state in the state-machine.
       // The state should be ended be the call followed by suspension check.\
       switch (label) {
           case 0:
               // The variables are (un)spilled automatically as long as they are represented as continuation's fields.
               // Ideally, there shall be only one local: 'result'. See suspend call's comment below.
               this.newArgs = new ArrayList<>();
               this.newArgs.add(this.bean);
               this.newArgs.addAll(Arrays.asList(this.args).subList(0, this.args.length - 2));
               // Every state in state-machine should increment the label, this way coroutine's resume will resume in
               // correct spot
               this.label++;
               // Pass 'this' as continuation parameter. This way it will be resumed upon child coroutine's completion.
               // Coroutines reuse the same variable 'result' to represent both results of suspend call and an argument of
               // resumeWith function. This way, the code works correctly for all outcomes: and if the child does not
               // suspend at all, and if it calls this object's 'resumeWith' upon completion.
               result = KCallables.callSuspend(function, newArgs.toArray(), this);
               // Coroutine is suspended
               if (result == IntrinsicsKt.getCOROUTINE_SUSPENDED()) return result;
               // FALLTHRU
           case 1:
               if (result == Unit.INSTANCE) return null;
               else return result;
               // FALLTHRU, but this should not matter
           default:
               throw new IllegalStateException("Incorrect label of coroutine: " + label + " when 2 is maximum value");
       }
   }
   
   @Override
   public Object invoke(CoroutineScope coroutineScope, Continuation<?> continuation) {
       this.scope = coroutineScope;
       this.completion = continuation;
       // The initial result does not matter as long as it is not Result.Failure. It gets thrown away anyway.
       return this.invokeSuspend(Unit.INSTANCE);
   }
}

В принципе, я постарался все места, которые могут быть непонятны, откомментировать.
Это, если кому любопытно, я переписал функцию https://github.com/zhangll00/spring-framework/blob/9b33b0ad58dcda1e3ea803d0c6468e17b24a4ad2/spring-core/kotlin-coroutines/src/main/kotlin/org/springframework/core/CoroutinesUtils.kt#L63
источник

Ⓢⓔⓡⓖ in Kotlin Moscow
Sergey Morgunov
Серёж, а кого ты подразумеваешь под бизнес-пользователями JMeter?
Jmeter это промежуточный инструмент. Ты для кого свою программу пишешь?
источник

SM

Sergey Morgunov in Kotlin Moscow
Ⓢⓔⓡⓖ
Jmeter это промежуточный инструмент. Ты для кого свою программу пишешь?
Ну я и JMeter не пишу 😀 Просто мне кажется, что по данному вопросу основные бенефициары будут контрибьютеры JMetet, а не бизнес-пользователи.
источник

Ⓢⓔⓡⓖ in Kotlin Moscow
Я не понял, причём здесь JMeter.
источник

Ⓢⓔⓡⓖ in Kotlin Moscow
Коллеги! Требуется найти ответ на вопрос бизнес-пользователя-не-программиста - какие выгоды он получит, если программисты будут писать программы с помощью корутин. Нужно два коротких и простых ответа: а) для бэкенда б) для фронтэнда (веб+мобилки).
источник

SM

Sergey Morgunov in Kotlin Moscow
Ⓢⓔⓡⓖ
Я не понял, причём здесь JMeter.
Ты кажется упустил самое начало 😀 Володя мейнтейнер JMeter и его вопрос про suspend функцию был задан именно с контекстом кодовой базы JMeter
источник