├── Makefile ├── README.md └── coroutine.cpp /Makefile: -------------------------------------------------------------------------------- 1 | 2 | coroutine: coroutine.cpp 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A super-simple "Lua-like" coroutine implementation for C++. 2 | 3 | To run the sample, download it and type "make." Then run "./coroutine." 4 | 5 | If you're interested in this, check out my [coro](https://github.com/mfichman/coro.git) library, which is much more robust and includes an asynchronous socket library. 6 | -------------------------------------------------------------------------------- /coroutine.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | class Coroutine { 8 | 9 | public: 10 | typedef void (*Function)(void); 11 | enum Status { NEW, RUNNING, FINISHED }; 12 | 13 | Coroutine(Function function) : 14 | status_(NEW), 15 | stack_(4096) { 16 | 17 | getcontext(&context_); 18 | context_.uc_stack.ss_sp = &stack_[0]; 19 | context_.uc_stack.ss_size = stack_.size(); 20 | context_.uc_link = 0; 21 | makecontext(&context_, function, 0); 22 | } 23 | 24 | void resume() { 25 | if (FINISHED == status_) { 26 | return; 27 | } 28 | if (NEW == status_) { 29 | status_ = RUNNING; 30 | } 31 | 32 | ucontext_t save = caller_; 33 | 34 | // The caller context becomes the current context 35 | swapcontext(&caller_, &context_); 36 | context_ = callee_; 37 | 38 | caller_ = save; 39 | } 40 | 41 | static void yield() { 42 | // The current context becomes the caller 43 | swapcontext(&callee_, &caller_); 44 | } 45 | 46 | static ucontext_t caller_; 47 | static ucontext_t callee_; 48 | 49 | private: 50 | Status status_; 51 | ucontext_t context_; 52 | std::vector stack_; 53 | 54 | }; 55 | 56 | ucontext_t Coroutine::caller_; 57 | ucontext_t Coroutine::callee_; 58 | 59 | void g() { 60 | std::cout << "x" << std::endl; 61 | Coroutine::yield(); 62 | std::cout << "z" << std::endl; 63 | } 64 | 65 | void f() { 66 | Coroutine co(g); 67 | co.resume(); 68 | 69 | std::cout << "a" << std::endl; 70 | Coroutine::yield(); 71 | std::cout << "b" << std::endl; 72 | Coroutine::yield(); 73 | std::cout << "c" << std::endl; 74 | 75 | co.resume(); 76 | } 77 | 78 | int main(int argc, char** argv) { 79 | Coroutine co(f); 80 | co.resume(); 81 | co.resume(); 82 | co.resume(); 83 | std::cout << "DONE" << std::endl; 84 | return 0; 85 | 86 | } 87 | --------------------------------------------------------------------------------