-1

How can I visualize the call stack of a single thread that is executing the co-routine functions?

Does any language implementation support co-routines running in different threads?

I came across the awesome Stack Overflow question Difference between a “coroutine” and a “thread”?. In this question, I saw this point:

[I]f you have a routine doing some work and it performs an operation you know will block for some time (i.e. a network request), with a co-routine you can immediately switch to another routine without the overhead of including the system scheduler in this decision - yes you the programmer must specify when co-routines can switch.

In JS, if I have a routine (some function) which is a CPU bound operation (not IO/Network request), then can I still use co-routines (i.e., generators in JS)? Or shall I use Web Workers so I don’t block the event loop (i.e. at least UI rendering happens)?

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
Pawan Kumar
  • 1,443
  • 2
  • 16
  • 30

1 Answers1

1

Let's look at a simple generator example:

const doubleGen = function*(initValue) {
  const value = yield initValue * 2;
  return value * 2;
};

const gen = doubleGen(2);

console.log("pre");
console.log(gen.next());
console.log("middle");
console.log(gen.next(4));
console.log("post");

We can rewrite this exactly as:

const doubleGen = (initValue) => {
  const yieldStatements = [ // the function body statements
    () => initValue * 2,
    (inputValue) => {
      const value = inputValue;
      return value * 2;
    }
  ];
  
  return {
    next(inputValue) {
      return {
        value: yieldStatements.shift()(inputValue),
        done: !yieldStatements.length
      }
    }
  }
};

const gen = doubleGen(2);

console.log("pre");
console.log(gen.next());
console.log("middle");
console.log(gen.next(4));
console.log("post");

So as you can see there is no magic in how generators actually work, as they simply use the iterator pattern to control the successive invocations one after another.

You can even dumb it down to just simple function invocation one after another, so it's all synchronous by default.

If the calculations are heavy you indeed can offload them to web-worker(s) which are essentially separate threads, and free your main thread for some time until the final payloads from those workers arrive.

So what I am trying to say is that the call stack would look like a call stack of executing any other bunch of normal functions, in a ordinary synchronous fashion. There is no special treatment just because there is a * sign or yield keyword.

Hope it clarifies.

Karen Grigoryan
  • 5,234
  • 2
  • 21
  • 35