Created
December 15, 2015 09:34
-
-
Save hghwng/20f2cf413c9fdaacd0dd to your computer and use it in GitHub Desktop.
Coroutine lib and demo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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