Как может быть реализована новая функция Async в C # 5.0 с Call / CC?

StackOverflow https://stackoverflow.com/questions/4070237

Вопрос

Я следую за новым объявлением о новом async Функция, которая будет в C # 5.0. У меня есть базовое понимание стиля прохождения продолжения и преобразования новый компилятор C # доставляет код, как этот фрагмент от Eric Lippert's Post:

async void ArchiveDocuments(List<Url> urls)
{
  Task archive = null;
  for(int i = 0; i < urls.Count; ++i)
  {
    var document = await FetchAsync(urls[i]);
    if (archive != null)
      await archive;
    archive = ArchiveAsync(document);
  }
}

Я знаю, что некоторые языки реализуют продолжения, по сравнению с Call-rection-продолжением (callcc), но я не очень понимаю, как это работает или что это делает именно.

Так вот вот вопрос: если anders et al. решил укусить пулю и просто реализовать callcc в C # 5.0 вместо async/await Специальный случай, как бы выглядел вышеупомянутый фрагмент?

Это было полезно?

Решение

Оригинальный ответ:

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

Ну, прежде всего, давайте подумаем о том, что «ждет». «ждут» принимает выражение типа Task<T>, получает avaiter и называет avaiter с текущим продолжением:

await FooAsync()

становится эффективно

var task = FooAsync();
var awaiter = task.GetAwaiter();
awaiter.BeginAwait(somehow get the current continuation);

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

var task = FooAsync();
var awaiter = task.GetAwaiter();
callcc awaiter.BeginAwait;

Другими словами:

await FooAsync()

не более чем

callcc FooAsync().GetAwaiter().BeginAwait;

Это отвечает на ваш вопрос?


Обновление № 1:

Как отмечает комментатор, ответ ниже предполагает шаблон генерации кода из версии «Просмотр технологии» функции ASYNC / aNAIT. На самом деле мы генерируем немного другой код в бета-версии функции, хотя логически это то же самое. Настоящий Codegen что-то вроде:

var task = FooAsync();
var awaiter = task.GetAwaiter();
if (!awaiter.IsCompleted)
{
    awaiter.OnCompleted(somehow get the current continuation);
    // control now returns to the caller; when the task is complete control resumes...
}
// ... here:
result = awaiter.GetResult();
// And now the task builder for the current method is updated with the result.

Обратите внимание, что это несколько сложнее, и обрабатывает случай, когда вы «ожидаете» результат, который уже был вычислен. Нет необходимости проходить через всю градус доступа в качестве контроля к вызывающему абоненту и снова подниматься там, где вы остановились, если результат, который вы ждете, на самом деле уже кэшируется в память для вас прямо здесь.

Таким образом, связь между «a ждать» и «CALLCC» не так просто, как это было в выпуске предварительного просмотра, но по-прежнему ясно, что мы по сути, делаем Callcc на «Occompleted» метода avaiter. Мы просто не делаем Calcc, если нам не нужно.


Обновление № 2:

Как этот ответ

https://stackoverflow.com/a/9826822/88656.

Из Timwi указывает, семантика вызова / CC и ждет не совсем одинаково; «True» Call / CC требует от того, что мы «захватываем» весь Продолжение метода в том числе весь стек вызова, или эквивалентно, что вся программа переписана в продолжение прохождения стиля.

Функция «aNAIT» больше похоже на «кооперативный вызов / CC»; Продолжение только захватывает «Что такое текущий Способ возврата задач собирается сделать дальше в точке ждут? "Если абонент метода возврата задач собирается сделать что-то интересное после завершения задачи, то это бесплатно зарегистрироваться его продолжение как продолжение задачи.

Другие советы

Я не эксперт на продолжениях, но я возьму удар по объяснению разницы между async / a ждать и call / cc. Конечно, это объяснение предполагает, что я понимаю Call / CC и Async / ждут, что я не уверен, что я делаю. Тем не менее, здесь идет ...

С C # 'async', вы говорите компилятору создать специальную версию этого конкретного метода, который понимает, как бутыло его состояние в структуру HeaP-Data, поэтому его можно «удалить из реального стека» и возобновить позже. В пределах Async-Context «a a a a a a a enaave» в том, что «Call / CC» в том, что он использует сгенерированные компиляторы объекты для установки состояния и сойти с «реального стека», пока задача не завершится. Однако, поскольку это компилятор, переписывающий асинхронный метод, который позволяет состоянию быть в бутыре, ждут только в пределах асинкового контекста.

В первоклассном вызове / CC языковая среда выполнения генерирует весь код, так что текущее продолжение может быть в бутылках в функцию продолжения вызовов (что делает ключевое слово ASYNC ненужным). Call / CC по-прежнему действует, как ждут, вызывая состояние текущего продолжения (подумайте о состоянии стека), который должен быть связан и передан как функцию для вызываемой функции. Один из способов сделать это - использовать кучи кадров для все Вызов функции, вместо кадров «стека». (Иногда упоминается как «Statured», как в «StateLel Python» или многих реализациях схемы) Еще одним способом удалить все данные из «Real Stack» и наполните ее в структуру данных кучи, прежде чем вызовать цель Call / CC Отказ

Некоторые сложные проблемы могут возникнуть, если есть призывы к внешним функциям (думаю, что dllimport) смешивается в стеке. Я подозреваю, что это причина, по которой они пошли с реализацией Async / await.

http://www.madore.org/~david/computers/callcc.html.


Поскольку в C # функция должна быть помечена как «Async», чтобы использовать эту механику, мне интересно, если бы это ключевое слово Async станет вирусом, который распространяется на множество функций во многих библиотек. Если это произойдет. В конечном итоге они могут реализовать, что они должны реализовывать первоклассный вызов / CC на уровне VM, а не на основании этой асинхронизации на основе этого компилятора. Время покажет. Тем не менее, это, безусловно, является полезным инструментом в контексте текущей среды C #.

Вроде бессмысленно скажу. Схема переводчиков часто реализует вызов / CC с состоянием, который захватывает локальное состояние на кучу. Который точно Какой C # 5.0 (или более правильно C # 2.0 итератор) также делает. Они сделал Реализуйте вызов / CC, абстракция, которую они придумали, довольно элегантно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top