Skip to content

Instantly share code, notes, and snippets.

@hghwng
Created December 15, 2015 09:34
Show Gist options
  • Save hghwng/20f2cf413c9fdaacd0dd to your computer and use it in GitHub Desktop.
Save hghwng/20f2cf413c9fdaacd0dd to your computer and use it in GitHub Desktop.
Coroutine lib and demo
#include <iostream>
#include <algorithm>
#include <string>
#include <stack>
using namespace std;
// coroutine start
#define _cr_cntr_start constexpr int _counter_start_val = __COUNTER__
#define _cr_cntr_next (__COUNTER__ - _counter_start_val)
#define _cr_return \
{ \
_stack.pop(); \
goto tag_yield; \
}
#define _cr_recurse(...) \
{ \
_stack.top().i += 1; \
_stack.emplace(__VA_ARGS__); \
goto tag_yield; \
} \
case _cr_cntr_next:
#define _cr_yield(_v) \
{ \
_stack.top().i += 1; \
_ret = _v; \
return true; \
} \
case _cr_cntr_next:
#define _cr_val(_name) auto &_name = _stack.top()._name;
#define _cr_def(_name, _context_type, _ret_type) \
bool _name(std::stack<_context_type> &_stack, _ret_type &_ret) { \
_cr_cntr_start; \
while (!_stack.empty())
#define _cr_end \
default: \
_cr_return; \
} \
tag_yield: \
continue; \
} \
return false
#define _cr_start \
switch (_stack.top().i) { \
case 0: \
#define _cr_call_init(_name, _context_type, ...) \
std::stack<_context_type> _cr_env_##_name; \
_cr_env_##_name.emplace(__VA_ARGS__)
#define _cr_call(_name, _ret) \
_name(_cr_env_##_name, _ret)
struct ContextBase {
int i;
ContextBase() : i(0) {}
};
// coroutine end
struct Node {
char v;
Node *l, *r;
Node() = default;
Node(char c): v(c), l(nullptr), r(nullptr) {}
};
void inorder(const Node *n) {
if (n == nullptr) return;
inorder(n->l);
cout << n->v;
inorder(n->r);
}
struct Context : public ContextBase {
Node *r;
Context(Node *r) : r(r) {}
};
_cr_def(cr_inorder_doit, Context, char) {
_cr_val(r);
_cr_start;
if (r == nullptr) _cr_return;
_cr_recurse(r->l);
_cr_yield(r->v);
_cr_recurse(r->r);
_cr_end;
}
void cr_inorder(Node *n) {
_cr_call_init(cr_inorder_doit, Context, n);
char ret;
while (_cr_call(cr_inorder_doit, ret)) {
fputc(ret, stdout);
}
}
string g_str;
Node *build() {
if (g_str.empty()) return nullptr;
auto c = g_str.back();
g_str.pop_back();
if (c == ' ') return nullptr;
auto n = new Node(c);
n->l = build();
n->r = build();
return n;
}
int main() {
g_str = "ABC DE G F ";
reverse(g_str.begin(), g_str.end());
auto root = build();
cout << "recursive: "; inorder(root); cout << endl;
cout << "coroutine: "; cr_inorder(root); cout << endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment