Stackless & stackful coroutines
От: x-code  
Дата: 21.01.15 08:33
Оценка:
Что такое stackful coroutines вполне понятно — в памяти создается дополнительный стек, на который переключается регистр-указатель стека процессора. И в нем можно все то же самое что и в основном — вызывать функции, возвращать значения и т.д.
А вот что такое stackless coroutines? Судя по названию — "безстековые", но тогда как они работают? В чем разница со stackful? Как они реализуются на низком уровне? Каковы преимущества и недостатки обоих подходов?
Re: Stackless & stackful coroutines
От: johny5 Новая Зеландия
Дата: 21.01.15 08:55
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Что такое stackful coroutines вполне понятно — в памяти создается дополнительный стек, на который переключается регистр-указатель стека процессора. И в нем можно все то же самое что и в основном — вызывать функции, возвращать значения и т.д.

XC>А вот что такое stackless coroutines? Судя по названию — "безстековые", но тогда как они работают? В чем разница со stackful? Как они реализуются на низком уровне? Каковы преимущества и недостатки обоих подходов?

Буквально сегодня читал что то из C++ proposals: stackless — это когда yield можно делать только из функции первой на стеке, то как со stackfull yield/await можно и во вложенных функциях. Т.е. в обоих случаях у них есть стек.

Впрочем терминология похоже ещё не целиком в этой области устоялась, готов послушать другие мнения.
Re: Stackless & stackful coroutines
От: chaotic-good  
Дата: 21.01.15 09:09
Оценка: 6 (3)
XC>А вот что такое stackless coroutines? Судя по названию — "безстековые", но тогда как они работают? В чем разница со stackful? Как они реализуются на низком уровне? Каковы преимущества и недостатки обоих подходов?

Stackless coroutine это когда компилятор строит конечный автомат (как в питоне или C#) и в месте вызова просто дергает соответствующие методы этого объекта. Соответственно, весь контекст хранится в этом объекте КА, а не на стеке.
Re: Stackless & stackful coroutines
От: Abyx Россия  
Дата: 21.01.15 10:47
Оценка: 22 (3)
Здравствуйте, x-code, Вы писали:

Stackless coroutines преобразуют код в state machine.
Для С++ это выглядит примерно так:

допустим, у нас есть простой класс task<T> (aka Promise aka future)
template<typename T>
class task {
public:
  // wait and return task result
  T get();

  // pass task result to |continuation|
  void then(function<void(T)> continuation);
};

template<typename T>
class task_completion_event {
public:
  void set(T t); // set task result
};

template<typename T> task<T> create_task(task_completion_event<T> completion);


Мы пишем следующий асинхронный код
task<vector<int>> g();
task<int> h(int x);

task<int> f(int x0) async {
  vector<int> v = await g();
  int sum = x0;
  for (int i = 0; i != v.size(); ++i) {
    sum += await h(v[i]);
  }
  return sum;
}

int main() {
  task<int> t = f(100);
  return t.get();
}


и компилятор переписывает f() в следующую функцию:
task<int> f(int x0) {
  struct Context {
    int x0;
    vector<int> v;
    int sum;
    int i;
    int x;

    task_completion_event<int> result;
    int state = 0;

    static void next(shared_ptr<Context> ctx) {
      for (;;) {
        switch (ctx->state) {
        case 0:
          g().then([ctx](vector<int> v){
              ctx->v = v;
              next(ctx);
          });

          ctx->state = 1;
          return;

        case 1:
          ctx->sum = ctx->x0;
          ctx->i = 0;

          ctx->state = 2;
          break;

        case 2:
          if (ctx->i != ctx->v.size())
            ctx->state = 3;
          else
            ctx->state = 5;
          break;

        case 3:
          h(ctx->v[ctx->i]).then([ctx](int x){
            ctx->x = x;
            next(ctx);
          });

          ctx->state = 4;
          return;

        case 4:
          ctx->sum += ctx->x;
          ++ctx->i;

          ctx->state = 2;
          break;

        case 5:
          ctx->result.set(ctx->sum);
          return;
      }
    }
  };

  shared_ptr<Context> ctx = make_shared<Context>();
  ctx->x0 = x0;
  task<int> t = create_task(ctx->result);
  Context::next(ctx);
  return t;
}
In Zen We Trust
Re: Stackless & stackful coroutines
От: c-smile Канада http://terrainformatica.com
Дата: 21.01.15 20:06
Оценка: 6 (2)
Здравствуйте, x-code, Вы писали:

XC>А вот что такое stackless coroutines? Судя по названию — "безстековые", но тогда как они работают? В чем разница со stackful? Как они реализуются на низком уровне? Каковы преимущества и недостатки обоих подходов?



stackless coroutine означает что в спящем состоянии она не использует стандартный стек thread/main-thread.
Текущее состояние SC сохраняется в некой переменной/блоке переменных. Эта переменная может быть на [чужом] стеке или в heap.

В состоянии исполнения, и до вызова yield, stackless coroutine использует stack of caller thread.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.