Возможно ли вообще получить ошибку StackOverflow с рекурсивными акторами, управляемыми событиями? - PullRequest
4 голосов
/ 06 мая 2011

Как сказано в комментариях, Combinatiors.loop стандартной библиотеки актеров предназначен для того, чтобы уберечь вас от переполнения стека, когда тело актера выполняется повторно.

Но имеет ли смысл использовать loop для акторов, управляемых событиями (react), когда обработка сообщений фактически [почти] всегда запланирована для выполнения в выделенном пуле потоков? Простой рекурсивный вызов тела представляется более эффективным вариантом.


Метод Reactor.seq (вызывается Combinatiors.loop) определяется следующим образом:

  private[actors] def seq[a, b](first: => a, next: => b): Unit = {
    val killNext = this.kill
    this.kill = () => {
      this.kill = killNext

      // to avoid stack overflow:
      // instead of directly executing `next`,
      // schedule as continuation
      scheduleActor({ case _ => next }, null)
      throw Actor.suspendException
    }
first
throw new KillActorControl

}

Предположим, next вызывается напрямую. В этом случае react выполняется немедленно, обработка сообщений запланирована , и субъект приостанавливается. Нет места для переполнения стека ...

Где я не прав?

1 Ответ

0 голосов
/ 06 мая 2011

loop - это конструкция общего назначения, которая может использоваться как для основанных на потоках, так и для событийных актеров. Если вы попытаетесь рекурсивно обработать сообщения субъекта, основанного на потоке, вы быстро получите переполнение стека (если ваша обработка сообщений не является хвостовой рекурсивной и может быть оптимизирована).

Что касается акторов, управляемых событиями, вы абсолютно правы - рекурсивная обработка будет более эффективной, если сценарий переполнения стека, специфичный для потоковых акторов, недопустим для событий, управляемых событиями (вы даже не должны сделать рекурсию оптимизируемой).

...