Continuations in C; easy asynchronous stuff

If you have worked with asynchronous stuff, you surely must have reached a point where you need to save your current context, in order to continue the computation after you’ve received some data asynchronously.

For example, let’s say you want to upload a file to a web service, then you need to wait for some kind of id, and then you can add tags to identify it.

The simplest way to do it would be to just block until you receive the id, and then tag it. That is easy, but in the meantime nothing else can be done, and if you have a UI you’ll just see an unresponsive application.

Another approach is to create a new thread, that way other stuff can keep running while your thread waits for the id. The problem here is that threads are not exactly easy to handle, and some UI’s aren’t particularity good at handling threads. Another problem is that threads are expensive, if you have many threads being created and destroyed rapidly you are probably wasting resources.

Then if you are not lazy, you might want to save the context in a separate structure, write a separate a callback to handle the response, and the continue the processing. That is not too difficult, there are no performance penalties and should play nicely with every other code you might be running. Unfortunately it’s tedious, and if you have many contexts to store, it becomes painful.

So, here comes continuations the rescue. The concept is really simple, you reach a point in your code where don’t have anything else to compute, so you yield to allow other computations to continue, and when the relevant data is ready, the context is resumed and your code continues the execution as if nothing happened.

file.send
yield id = file.get_id # wait, but let other stuff to happen
tags.send(id)

It sound too good to be truth, and it is. Most languages don’t have support for this continuations, so you end up with ugly workarounds in order to make them work.

Fortunately there are some C primitives you can use for continuations. Wikipedia has a nice list of alternatives.

So I implemented something very basic based on Marc Lehmann’s libcoro, which makes this code possible:

struct task *test_task (const char *str) {
  struct task *t;
  void helper (struct task *t) {
    const char *tmp = str;
    printf ("%s: test: tmp=%s\n", __func__, tmp);
    task_yield (t);
    printf ("%s: after yield: tmp=%s\n", __func__, tmp);
    task_complete (t);
  }
  t = task_new (helper);
  return t;
}

The output goes like this:
main: begin
helper: test: tmp=hello world!
main: foo
helper: after yield: tmp=hello world!
main: end

I still haven’t used this for anything on real-world scenarios, but looks like an interesting idea to explore.

4 thoughts on “Continuations in C; easy asynchronous stuff

  1. Felipe,
    You seem to live in Mexico, few careers include continuations in their curricula.
    Have you studied continuations in your school?

    Like

  2. These are coroutines, not continuations. Real continuations allow you to arbitrarily jump back and forth in your program’s execution, e.g. you can go back, change a variabale, the code will execute again but differently, with a different outcome, then go back into forward in the code, to the original outcome, continue, go back to the different outcome, etc…

    Imagine your program is a time traveler. It goes back in time, kills someone’s grandparents, and as that timeline of your program executes, that someone is never born, but then goes into the timeline where the someone was born, interact with the someone, then goes back into the timeline without the one…

    Like

  3. solo por curiosidad:
    I only know one Licenciatura in Ciencias de la Computación in all Mexico, one mathematics career with some area on computer science and no more.
    All other careers are called Licenciaturas en Informática, en informática administrativa o en tecnologías de la información.
    The first curricula in Ciencias de la Informática had an area in computation, but became another career in information technologies.
    There are also some careers in computing engineering more focused on electronics.
    Mainly in public universities, and only 2 or 3 private universities have a more or less decent curricula.
    It is unbelievable but the majority of people on the area ignore the foundations on computing.
    Which careers did you find where continuations are taught?
    Do they have courses about theoretical subjects or they only adopted a course on Scheme or Racket like the PLT?
    For graduate studies I only know 2 serious programs in computer science.

    Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.