LINUX.ORG.RU
ФорумTalks

рекурсия как диагноз или я чего-то не понимаю

 


0

2

https://github.com/jurmous/etcd4j/blob/master/src/main/java/mousio/client/pro...

 public T get() throws Exception {
    if (!waitForPromiseSuccess()) {
      return this.get(); //метод ничто не прегружает
    }

    if (response != null) {
      return response;
    } else {
...
    }
}

protected boolean waitForPromiseSuccess() throws IOException, TimeoutException {
    if (!promise.isDone() && !promise.isCancelled()) {
      Promise<T> listeningPromise = this.promise;
      listeningPromise.awaitUninterruptibly();
      if (listeningPromise != this.promise) {
        return false;
      }
      this.handlePromise(promise);
    }
    return true;
}

Поясните что здесь происходит, и зачем оно так? Или это просто песец сбежал из парижской палаты мер и весов и своими пушистыми лапками пишет код?

Deleted

ну да, это рекурсия. Повторять, пока не случится promise.isDone() или promise.isCancelled()

смущает, что он повторяет это без всякой паузы, и рекурсией вместо цикла, т.е. не знает что бесконечной рекурсии в джаве нет

и вапщет оно перегружается в классе-наследнике EtcdResponsePromise, но в нем такое же говно

stevejobs ★★★★☆
()
Последнее исправление: stevejobs (всего исправлений: 1)

Оверфлоу вижу я (в жаве можно отхватить оверфлоу стека?).

А ваще просто тупо ждет, пока promise.isDone() или promise.isCancelled().

Ну и еще может выкинуть ексепшн вот тут, однако listeningPromise.awaitUninterruptibly()

slaykovsky ★★★
()
Ответ на: комментарий от stevejobs

смущает, что он повторяет это без всякой паузы

awaitUninterruptibly()
Causes the current thread to wait until it is signalled.

Чем не пауза?

xaizek ★★★★★
()
Ответ на: комментарий от Deleted

может там какой-то адовый джава-агент типа Quasar или еще какой-то аоп, который waitForPromiseSuccess оборачивает кодом с таймаутами и выравнивает рекурсию в цикл. Но чего-то не находится там квазара...

stevejobs ★★★★☆
()
Ответ на: комментарий от stevejobs

нет там никаких агентов, я прозреваю агенты жаваскрипта в голове автора кода, судя по наличию промисов, которых в жаве заменяет future

Deleted
()
Ответ на: комментарий от xaizek

а, ага, и этот метод дергается из Netty, то есть даже должен работать

stevejobs ★★★★☆
()
Ответ на: комментарий от Deleted

а это уже в Нетти

    
@Override
    public Promise<V> awaitUninterruptibly() {
        if (isDone()) {
            return this;
        }

        checkDeadLock();

        boolean interrupted = false;
        synchronized (this) {
            while (!isDone()) {
                incWaiters();
                try {
                    wait();
                } catch (InterruptedException e) {
                    // Interrupted while waiting.
                    interrupted = true;
                } finally {
                    decWaiters();
                }
            }
        }

        if (interrupted) {
            Thread.currentThread().interrupt();
        }

        return this;
    }
stevejobs ★★★★☆
()
Ответ на: а это уже в Нетти от stevejobs

с нетти там тоже какойто фокус, либо они его не умеют готовить, либо там какоето подергивание, но выглючивается так: https://github.com/codeabovelab/haven-platform/issues/20

"main@1" prio=5 tid=0x1 nid=NA waiting
  java.lang.Thread.State: WAITING
	  at java.lang.Object.wait(Object.java:-1)
	  at java.lang.Object.wait(Object.java:502)
	  at io.netty.util.concurrent.DefaultPromise.awaitUninterruptibly(DefaultPromise.java:261)
	  at mousio.client.promises.ResponsePromise.waitForPromiseSuccess(ResponsePromise.java:189)
	  at mousio.etcd4j.promises.EtcdResponsePromise.get(EtcdResponsePromise.java:58)
	  at mousio.etcd4j.promises.EtcdResponsePromise.get(EtcdResponsePromise.java:59)
...below strings repeated many times....
	  at mousio.etcd4j.promises.EtcdResponsePromise.get(EtcdResponsePromise.java:59)
	  at mousio.etcd4j.promises.EtcdResponsePromise.get(EtcdResponsePromise.java:59)
	  at com.codeabovelab.dm.cluman.ds.kv.etcd.EtcdClientWrapper.set(EtcdClientWrapper.java:155)

причем, как позже выяснилось сервер отвечает что-то (там ошибка), но код клиента залипает в этом своем подергивании пока не кончится стек

Deleted
()
Ответ на: комментарий от Deleted

в нетти код синхронизуется на this (this самого Promise), а вызывающий метод waitForPromiseSuccess не синхронизован вообще. В общем, это тупо не thread-safe код, тебе нужно обмазать его еще одной оберткой syncWaitForPromiseSuccess :)

stevejobs ★★★★☆
()
Последнее исправление: stevejobs (всего исправлений: 1)
Ответ на: комментарий от stevejobs

вызывающий метод waitForPromiseSuccess не синхронизован вообще

там контракт от Future а она этого не требует, но конечно это никак не помогает 8)

Deleted
()

Сделай фикс и пришли пул риквест. Посмотри на отмазки.

invy ★★★★★
()
Ответ на: комментарий от slaykovsky

Оверфлоу вижу я (в жаве можно отхватить оверфлоу стека?).

Джава не оптимизирует хвостовую рекурсию? // Не джавист

qrck ★★
()

Нашёл какаху и радуется, как дитя.

HeipaVai1o
()

Рекурсия - зло и мало где она оправдана. Дети, не пишите так, как в стартовом посте.

peregrine ★★★★★
()
Ответ на: комментарий от qrck

Джава не оптимизирует хвостовую рекурсию?

нет. всё что понаписано сверху jvm и хочет использовать бесконечные рекурсии немного с этим заморачиваются. в скале разворачивают в цикл, в Clojure специальный синтаксис.

vtVitus ★★★★★
()

if (!promise.isDone() && !promise.isCancelled())

if (!promise.isDone() || !promise.isCancelled())
promise же не может быть одновременно отменено и сделано?
p.s. имхо

etwrq ★★★★★
()
Ответ на: комментарий от stevejobs

Смотря что считать популярными технологиями) Lua, JS, Erlang

ymn ★★★★★
()
Ответ на: комментарий от stevejobs

Многие C++ компиляторы поддерживают, но выключено по умолчанию.

Из managed языков, похоже мало кто умеет.

В случае .NET-а, F# умеет tail recursion (в определенных средах F# вполне даже популярный язык).

Из JVM языков, говорят Kotlin поддерживает хвостовую рекурсию, но требуется указать «tailrec» в заголовке метода. Я на Kotlin сам делал пару проектов (один из 3х моих любимых языков), но с рекурсией не игрался (не большой любитель лепить рекурсию там, где она не нужна).

Ну и стыдно упоминать, но говорят JavaScript в последнее версии стандарта требует реализации поддержки хвостовой рекурсии. На данный момент реализовано в Safari и Chrome.

qrck ★★
()
Ответ на: комментарий от qrck

В случае .NET-а, F# умеет tail recursion (в определенных средах F# вполне даже популярный язык).

там очень серьёзные ограничения. https://habrahabr.ru/post/143690/

Из JVM языков, говорят Kotlin поддерживает хвостовую рекурсию

точно так же как и скала разворачивает в циклы.

только js и только в strict моде. то есть на текущий момент фактически никто.

vtVitus ★★★★★
()
Ответ на: комментарий от Siado

Afaik все современные C++ компиляторы умеют. Смысл в том, что в конструкции вида

int func(int a, int b, int c)
{
    ... какие-то условия ...
       return func(другие параметры);

    ... еще код возможно...
}

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

Профит такого подхода - даже миллиард вложенных рекурсивных вызовов не приведет к срыву стека.

Польза - скорее академическая ;) По подобному коду можно узнать любителей всякого там хаскеля.

qrck ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.