#include <stdio.h>

#ifndef ASYNC_H
#define ASYNC_H

#define async(...) int *_state_ = &(__VA_ARGS__); switch (*_state_) while (1) if (1) {*_state_ = 1; case 1: return 1;} else default:
#define await(...) if (!(*_state_ = __LINE__)); else case __LINE__: switch (0) while (1) if (!(__VA_ARGS__)) return 0; else if (1) break; else default:
#define yield if (0) case __LINE__:; else switch (0) while (1) if (1) {*_state_ = __LINE__; return 0;} else default:
#define leave switch (0) while (1) if (1) {*_state_ = 1; return 1;} else default:
#define until(...) while (!(__VA_ARGS__))

#endif

typedef union {
	struct {
		int n;
		int i;
		int state;
	};
	int result;
} write_async_task;

int write_async(write_async_task *t) {
	async (t->state) {
		printf("write %d: start\n", t->n);
		await (t->i >= t->n) {
			printf("write %d: %d\n", t->n, t->i);
			++t->i;
		}
		printf("write %d: end\n", t->n);
		leave t->result = t->i;
	}
}

typedef struct {
	int jid;
	int n;
	int state;
	write_async_task write_task;
} job_task;

int job(job_task *t) {
	async (t->state) {
		printf("job %d: before write\n", t->jid);
		t->write_task = (write_async_task){.n = t->n};
		await (write_async(&t->write_task));
		printf("job %d: written %d bytes\n", t->jid, t->write_task.result);
	}
}

int main(void) {
	puts("program start");
	job_task j1 = {.jid = 1, .n = 3};
	job_task j2 = {.jid = 2, .n = 7};
	until (
		job(&j1) &
		job(&j2)
	);
	job_task jobs[] = {
		{.jid = 3, .n = 7},
		{.jid = 4, .n = 9},
		{.jid = 5, .n = 4},
		{.jid = 6, .n = 5}
	};
	int jobs_n = sizeof(jobs) / sizeof(jobs[0]);
	while (jobs_n > 0) {
		for (int i = 0; i < jobs_n; ++i) {
			if (job(&jobs[i])) {
				jobs[i--] = jobs[--jobs_n];
			}
		}
	}
	puts("program end");
}
