Last active
June 17, 2020 16:17
-
-
Save heiner/671f1c53406cecc7987f067c7f34a335 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| cmake_minimum_required(VERSION 3.10) | |
| project(cppgen VERSION 0.0.1 LANGUAGES CXX) | |
| set(CMAKE_CXX_STANDARD 11) | |
| set(CMAKE_CXX_STANDARD_REQUIRED ON) | |
| link_libraries(pthread) | |
| add_executable(cppgen cppgen.cc) | |
| add_executable(cppgen-dup2 cppgen-dup2.cc) | |
| add_executable(cppgen-lock cppgen-lock.cc) | |
| add_executable(cppgen-uc cppgen-uc.cc) | |
| add_executable(cppnogen cppnogen.cc) | |
| add_executable(cppgen-fc cppgen-fc.cc) | |
| target_include_directories(cppgen-fc PRIVATE /Users/hnr/src/deboost.context/include) | |
| target_link_options(cppgen-fc PRIVATE /Users/hnr/src/deboost.context/build/libfcontext.a) |
This file contains hidden or 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
| // Cf. https://github.com/python/cpython/blob/2.7/Demo/threads/Generator.py | |
| #include <termios.h> | |
| #include <unistd.h> | |
| #include <cassert> | |
| #include <cstdio> | |
| #include <chrono> | |
| #include <iostream> | |
| #include <thread> | |
| int max = 4; | |
| struct tty_restore { | |
| tty_restore(int fd = STDIN_FILENO) : fd(fd) { | |
| tcgetattr(fd, &old); | |
| tty = old; | |
| tty.c_lflag &= ~ICANON; | |
| tty.c_lflag &= ~ECHO; | |
| set(); | |
| } | |
| ~tty_restore() { clear(); } | |
| void set() { tcsetattr(fd, TCSANOW, &tty); } | |
| void clear() { tcsetattr(fd, TCSANOW, &old); } | |
| int fd; | |
| struct termios old, tty; | |
| }; | |
| struct Generator { | |
| Generator() : std_stdout(dup(STDOUT_FILENO)) { | |
| pipe(pipe_stdout); | |
| pipe(pipe_lock); | |
| } | |
| ~Generator() { | |
| if (started) { | |
| thread_.join(); | |
| restore_stdout(); | |
| } | |
| for (int i = 0; i < 2; ++i) { | |
| close(pipe_stdout[i]); | |
| close(pipe_lock[i]); | |
| } | |
| } | |
| template <class Function> | |
| std::string start(Function f) { | |
| assert(!started); | |
| pipe_as_stdout(); | |
| thread_ = std::thread(f, this); | |
| started = true; | |
| return get(); | |
| } | |
| char put() { | |
| // Producer has done one step. Get one char from consumer. | |
| char c = '\0'; | |
| std::cout << c; | |
| std::cout.flush(); | |
| read(pipe_lock[0], &c, 1); | |
| return c; | |
| } | |
| void end() { | |
| // Producer is done. | |
| std::cout << '\0'; | |
| std::cout.flush(); | |
| } | |
| std::string get() { | |
| std::string result(BUFSIZ, ' '); | |
| ssize_t size; | |
| size_t length = 0; | |
| size_t remaining = result.length(); | |
| do { | |
| if (remaining == 0) { | |
| result.resize(2 * result.length()); | |
| remaining = result.length() - length; | |
| } | |
| size = read(pipe_stdout[0], static_cast<void *>(&(result[length])), | |
| remaining); | |
| assert(size > 0); | |
| length += size; | |
| remaining -= size; | |
| } while (result[length - 1] != '\0'); | |
| result.resize(length - 1); | |
| restore_stdout(); | |
| return result; | |
| } | |
| std::string send(char c) { | |
| pipe_as_stdout(); | |
| write(pipe_lock[1], (void *)&c, 1); | |
| return get(); | |
| } | |
| void pipe_as_stdout() { | |
| fflush(stdout); | |
| assert(dup2(pipe_stdout[1], STDOUT_FILENO) != -1); | |
| } | |
| void restore_stdout() { assert(dup2(std_stdout, STDOUT_FILENO) != -1); } | |
| std::thread thread_; | |
| int pipe_stdout[2]; | |
| int std_stdout; | |
| int pipe_lock[2]; | |
| bool started = false; | |
| }; | |
| void mainloop(Generator *g) { | |
| tty_restore r; | |
| char input; | |
| for (int i = 1; i < max; ++i) { | |
| std::cout << " #" << i << " >>> "; | |
| input = g->put(); | |
| std::cout << "Last input: " << static_cast<int>(input); | |
| } | |
| g->end(); | |
| } | |
| int main(int argc, char **argv) { | |
| { | |
| if (argc > 1) max = std::stoi(argv[1]); | |
| Generator g; | |
| auto start = std::chrono::system_clock::now(); | |
| std::string output = g.start([](Generator *g) { mainloop(g); }); | |
| auto now = std::chrono::system_clock::now(); | |
| // std::cout << '(' << output << ')'; | |
| for (int i = 1; i < max; ++i) { | |
| output = g.send(static_cast<char>(i)); | |
| if (i % 10000 == 0) { | |
| now = std::chrono::system_clock::now(); | |
| std::chrono::duration<double> elapsed = now - start; | |
| std::cout << i << ": " << 1000.0 / elapsed.count() << " SPS" | |
| << std::endl; | |
| start = now; | |
| } | |
| // std::cout << '(' << output << ')'; | |
| } | |
| } | |
| std::cout << std::endl << "All done." << std::endl; | |
| } |
This file contains hidden or 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
| // From tscmoo at | |
| // https://gist.github.com/tscmoo/a182a44a7ec8f22a16fabce5a48f946a | |
| #include <unistd.h> | |
| #include <cassert> | |
| #include <cstdio> | |
| #include <chrono> | |
| #include <iostream> | |
| #include <thread> | |
| #include <vector> | |
| #include <fcontext/fcontext.h> | |
| int max = 4; | |
| #define STACK_SIZE (1 << 15) // 32KiB | |
| struct Generator { | |
| Generator() : stack(create_fcontext_stack(STACK_SIZE)) { | |
| pipe(pipe_stdout); | |
| pipe(pipe_lock); | |
| out = fdopen(pipe_stdout[1], "w"); | |
| } | |
| ~Generator() { | |
| fclose(out); | |
| for (int i = 0; i < 2; ++i) { | |
| close(pipe_stdout[i]); | |
| close(pipe_lock[i]); | |
| } | |
| destroy_fcontext_stack(&stack); | |
| } | |
| fcontext_stack_t stack; | |
| fcontext_t generatorcontext; | |
| fcontext_t returncontext; | |
| template <class Function> | |
| std::string start(Function f) { | |
| assert(!started); | |
| std::function<void(fcontext_transfer_t)> innerf = | |
| [&](fcontext_transfer_t t) { | |
| returncontext = t.ctx; | |
| f(this); | |
| }; | |
| auto corofn = [](fcontext_transfer_t t) { | |
| auto f = (std::function<void(fcontext_transfer_t)> *)t.data; | |
| (*f)(t); | |
| }; | |
| generatorcontext = make_fcontext(stack.sptr, stack.ssize, | |
| (void (*)(fcontext_transfer_t))corofn); | |
| fcontext_transfer_t t = jump_fcontext(generatorcontext, &innerf); | |
| generatorcontext = t.ctx; | |
| started = true; | |
| return get(); | |
| } | |
| char put() { | |
| // Producer has done one step. Get one char from consumer. | |
| char c; | |
| end(); | |
| read(pipe_lock[0], &c, 1); | |
| return c; | |
| } | |
| void end() { | |
| fflush(out); | |
| char c = '\0'; | |
| write(pipe_stdout[1], &c, 1); | |
| fcontext_transfer_t t = jump_fcontext(returncontext, NULL); | |
| returncontext = t.ctx; | |
| } | |
| std::string get() { | |
| std::string result(BUFSIZ, ' '); | |
| ssize_t size; | |
| size_t length = 0; | |
| size_t remaining = result.length(); | |
| do { | |
| if (remaining == 0) { | |
| result.resize(2 * result.length()); | |
| remaining = result.length() - length; | |
| } | |
| size = read(pipe_stdout[0], static_cast<void *>(&(result[length])), | |
| remaining); | |
| assert(size > 0); | |
| length += size; | |
| remaining -= size; | |
| } while (result[length - 1] != '\0'); | |
| result.resize(length - 1); | |
| return result; | |
| } | |
| std::string send(char c) { | |
| write(pipe_lock[1], (void *)&c, 1); | |
| jump_fcontext(generatorcontext, NULL); | |
| return get(); | |
| } | |
| int pipe_stdout[2]; | |
| int std_stdout; | |
| int pipe_lock[2]; | |
| bool started = false; | |
| FILE *out; | |
| }; | |
| void mainloop(Generator *g) { | |
| char input; | |
| for (int i = 1; i < max; ++i) { | |
| fprintf(g->out, " #%d >>> ", i); | |
| input = g->put(); | |
| fprintf(g->out, "Last input: %i", static_cast<int>(input)); | |
| } | |
| g->end(); | |
| } | |
| int main(int argc, char **argv) { | |
| { | |
| if (argc > 1) max = std::stoi(argv[1]); | |
| Generator g; | |
| auto start = std::chrono::system_clock::now(); | |
| std::string output = g.start([](Generator *g) { mainloop(g); }); | |
| auto now = std::chrono::system_clock::now(); | |
| for (int i = 1; i < max; ++i) { | |
| output = g.send(static_cast<char>(i)); | |
| if (i % 10000 == 0) { | |
| now = std::chrono::system_clock::now(); | |
| std::chrono::duration<double> elapsed = now - start; | |
| std::cout << i << ": " << 1000.0 / elapsed.count() << " SPS" | |
| << std::endl; | |
| start = now; | |
| } | |
| // std::cout << '(' << output << ')'; | |
| } | |
| } | |
| std::cout << std::endl << "All done." << std::endl; | |
| } |
This file contains hidden or 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
| // Cf. https://github.com/python/cpython/blob/2.7/Demo/threads/Generator.py | |
| #include <unistd.h> | |
| #include <cassert> | |
| #include <cstdio> | |
| #include <chrono> | |
| #include <condition_variable> | |
| #include <iostream> | |
| #include <mutex> | |
| #include <thread> | |
| int max = 4; | |
| struct Generator { | |
| Generator() | |
| : prod_lock_(mu_, std::defer_lock), cons_lock_(mu_, std::defer_lock) { | |
| pipe(pipe_stdout); | |
| pipe(pipe_lock); | |
| out = fdopen(pipe_stdout[1], "w"); | |
| } | |
| ~Generator() { | |
| if (started) thread_.join(); | |
| fclose(out); | |
| for (int i = 0; i < 2; ++i) { | |
| close(pipe_stdout[i]); | |
| close(pipe_lock[i]); | |
| } | |
| } | |
| template <class Function> | |
| std::string start(Function f) { | |
| assert(!started); | |
| prod_lock_.lock(); | |
| producer_ = true; | |
| thread_ = std::thread(f, this); | |
| started = true; | |
| return get(); | |
| } | |
| char put() { | |
| // Producer has done one step. Get one char from consumer. | |
| char c; | |
| end(); | |
| prod_lock_.lock(); | |
| while (!producer_) { | |
| cv_.wait(prod_lock_); | |
| } | |
| read(pipe_lock[0], &c, 1); | |
| return c; | |
| } | |
| void end() { | |
| char c = '\0'; | |
| write(pipe_stdout[1], &c, 1); | |
| producer_ = false; | |
| prod_lock_.unlock(); | |
| cv_.notify_one(); | |
| } | |
| std::string get() { | |
| cons_lock_.lock(); | |
| while (producer_) { | |
| cv_.wait(cons_lock_); | |
| } | |
| std::string result(BUFSIZ, ' '); | |
| ssize_t size; | |
| size_t length = 0; | |
| size_t remaining = result.length(); | |
| do { | |
| if (remaining == 0) { | |
| result.resize(2 * result.length()); | |
| remaining = result.length() - length; | |
| } | |
| size = read(pipe_stdout[0], static_cast<void *>(&(result[length])), | |
| remaining); | |
| assert(size > 0); | |
| length += size; | |
| remaining -= size; | |
| } while (result[length - 1] != '\0'); | |
| result.resize(length - 1); | |
| return result; | |
| } | |
| std::string send(char c) { | |
| write(pipe_lock[1], (void *)&c, 1); | |
| producer_ = true; | |
| cons_lock_.unlock(); | |
| cv_.notify_one(); | |
| return get(); | |
| } | |
| std::thread thread_; | |
| int pipe_stdout[2]; | |
| int std_stdout; | |
| int pipe_lock[2]; | |
| bool started = false; | |
| FILE *out; | |
| std::mutex mu_; | |
| std::unique_lock<std::mutex> prod_lock_; // needs to persist. | |
| std::unique_lock<std::mutex> cons_lock_; // needs to persist. | |
| std::condition_variable cv_; | |
| bool producer_; | |
| }; | |
| void mainloop(Generator *g) { | |
| char input; | |
| for (int i = 1; i < max; ++i) { | |
| fprintf(g->out, " #%d >>> ", i); | |
| input = g->put(); | |
| fprintf(g->out, "Last input: %i", static_cast<int>(input)); | |
| } | |
| g->end(); | |
| } | |
| int main(int argc, char **argv) { | |
| { | |
| if (argc > 1) max = std::stoi(argv[1]); | |
| Generator g; | |
| auto start = std::chrono::system_clock::now(); | |
| std::string output = g.start([](Generator *g) { mainloop(g); }); | |
| auto now = std::chrono::system_clock::now(); | |
| // std::cout << '(' << output << ')'; | |
| for (int i = 1; i < max; ++i) { | |
| output = g.send(static_cast<char>(i)); | |
| if (i % 10000 == 0) { | |
| now = std::chrono::system_clock::now(); | |
| std::chrono::duration<double> elapsed = now - start; | |
| std::cout << i << ": " << 1000.0 / elapsed.count() << " SPS" | |
| << std::endl; | |
| start = now; | |
| } | |
| // std::cout << '(' << output << ')'; | |
| } | |
| } | |
| std::cout << std::endl << "All done." << std::endl; | |
| } |
This file contains hidden or 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
| // From tscmoo at | |
| // https://gist.github.com/tscmoo/a182a44a7ec8f22a16fabce5a48f946a | |
| #include <unistd.h> | |
| #include <cassert> | |
| #include <cstdio> | |
| #include <chrono> | |
| #include <iostream> | |
| #include <thread> | |
| #include <vector> | |
| #if defined(__APPLE__) | |
| #define _XOPEN_SOURCE 1 | |
| #endif | |
| #include <ucontext.h> | |
| int max = 4; | |
| #define STACK_SIZE (1 << 15) // 32KiB | |
| struct Generator { | |
| Generator() { | |
| pipe(pipe_stdout); | |
| pipe(pipe_lock); | |
| out = fdopen(pipe_stdout[1], "w"); | |
| } | |
| ~Generator() { | |
| fclose(out); | |
| for (int i = 0; i < 2; ++i) { | |
| close(pipe_stdout[i]); | |
| close(pipe_lock[i]); | |
| } | |
| } | |
| std::vector<char> stack; | |
| ucontext_t generatorcontext; | |
| ucontext_t returncontext; | |
| template <class Function> | |
| std::string start(Function f) { | |
| assert(!started); | |
| stack.resize(STACK_SIZE); | |
| getcontext(&generatorcontext); | |
| generatorcontext.uc_stack.ss_sp = stack.data(); | |
| generatorcontext.uc_stack.ss_size = stack.size(); | |
| makecontext(&generatorcontext, (void (*)())(void (*)(Generator *))f, 1, | |
| this); | |
| swapcontext(&returncontext, &generatorcontext); | |
| started = true; | |
| return get(); | |
| } | |
| char put() { | |
| // Producer has done one step. Get one char from consumer. | |
| char c; | |
| end(); | |
| read(pipe_lock[0], &c, 1); | |
| return c; | |
| } | |
| void end() { | |
| fflush(out); | |
| char c = '\0'; | |
| write(pipe_stdout[1], &c, 1); | |
| swapcontext(&generatorcontext, &returncontext); | |
| } | |
| std::string get() { | |
| std::string result(BUFSIZ, ' '); | |
| ssize_t size; | |
| size_t length = 0; | |
| size_t remaining = result.length(); | |
| do { | |
| if (remaining == 0) { | |
| result.resize(2 * result.length()); | |
| remaining = result.length() - length; | |
| } | |
| size = read(pipe_stdout[0], static_cast<void *>(&(result[length])), | |
| remaining); | |
| assert(size > 0); | |
| length += size; | |
| remaining -= size; | |
| } while (result[length - 1] != '\0'); | |
| result.resize(length - 1); | |
| return result; | |
| } | |
| std::string send(char c) { | |
| write(pipe_lock[1], (void *)&c, 1); | |
| swapcontext(&returncontext, &generatorcontext); | |
| return get(); | |
| } | |
| int pipe_stdout[2]; | |
| int std_stdout; | |
| int pipe_lock[2]; | |
| bool started = false; | |
| FILE *out; | |
| }; | |
| void mainloop(Generator *g) { | |
| char input; | |
| for (int i = 1; i < max; ++i) { | |
| fprintf(g->out, " #%d >>> ", i); | |
| input = g->put(); | |
| fprintf(g->out, "Last input: %i", static_cast<int>(input)); | |
| } | |
| g->end(); | |
| } | |
| int main(int argc, char **argv) { | |
| { | |
| if (argc > 1) max = std::stoi(argv[1]); | |
| Generator g; | |
| auto start = std::chrono::system_clock::now(); | |
| std::string output = g.start([](Generator *g) { mainloop(g); }); | |
| auto now = std::chrono::system_clock::now(); | |
| // std::cout << '(' << output << ')'; | |
| for (int i = 1; i < max; ++i) { | |
| output = g.send(static_cast<char>(i)); | |
| if (i % 10000 == 0) { | |
| now = std::chrono::system_clock::now(); | |
| std::chrono::duration<double> elapsed = now - start; | |
| std::cout << i << ": " << 1000.0 / elapsed.count() << " SPS" | |
| << std::endl; | |
| start = now; | |
| } | |
| // std::cout << '(' << output << ')'; | |
| } | |
| } | |
| std::cout << std::endl << "All done." << std::endl; | |
| } |
This file contains hidden or 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
| // Cf. https://github.com/python/cpython/blob/2.7/Demo/threads/Generator.py | |
| #include <unistd.h> | |
| #include <cassert> | |
| #include <cstdio> | |
| #include <chrono> | |
| #include <iostream> | |
| #include <thread> | |
| int max = 4; | |
| struct Generator { | |
| Generator() { | |
| pipe(pipe_stdout); | |
| pipe(pipe_lock); | |
| out = fdopen(pipe_stdout[1], "w"); | |
| } | |
| ~Generator() { | |
| if (started) thread_.join(); | |
| fclose(out); | |
| for (int i = 0; i < 2; ++i) { | |
| close(pipe_stdout[i]); | |
| close(pipe_lock[i]); | |
| } | |
| } | |
| template <class Function> | |
| std::string start(Function f) { | |
| assert(!started); | |
| thread_ = std::thread(f, this); | |
| started = true; | |
| return get(); | |
| } | |
| char put() { | |
| // Producer has done one step. Get one char from consumer. | |
| char c; | |
| end(); | |
| read(pipe_lock[0], &c, 1); | |
| return c; | |
| } | |
| void end() { | |
| char c = '\0'; | |
| write(pipe_stdout[1], &c, 1); | |
| } | |
| std::string get() { | |
| std::string result(BUFSIZ, ' '); | |
| ssize_t size; | |
| size_t length = 0; | |
| size_t remaining = result.length(); | |
| do { | |
| if (remaining == 0) { | |
| result.resize(2 * result.length()); | |
| remaining = result.length() - length; | |
| } | |
| size = read(pipe_stdout[0], static_cast<void *>(&(result[length])), | |
| remaining); | |
| assert(size > 0); | |
| length += size; | |
| remaining -= size; | |
| } while (result[length - 1] != '\0'); | |
| result.resize(length - 1); | |
| return result; | |
| } | |
| std::string send(char c) { | |
| write(pipe_lock[1], (void *)&c, 1); | |
| return get(); | |
| } | |
| std::thread thread_; | |
| int pipe_stdout[2]; | |
| int std_stdout; | |
| int pipe_lock[2]; | |
| bool started = false; | |
| FILE *out; | |
| }; | |
| void mainloop(Generator *g) { | |
| char input; | |
| for (int i = 1; i < max; ++i) { | |
| fprintf(g->out, " #%d >>> ", i); | |
| input = g->put(); | |
| fprintf(g->out, "Last input: %i", static_cast<int>(input)); | |
| } | |
| g->end(); | |
| } | |
| int main(int argc, char **argv) { | |
| { | |
| if (argc > 1) max = std::stoi(argv[1]); | |
| Generator g; | |
| auto start = std::chrono::system_clock::now(); | |
| std::string output = g.start([](Generator *g) { mainloop(g); }); | |
| auto now = std::chrono::system_clock::now(); | |
| // std::cout << '(' << output << ')'; | |
| for (int i = 1; i < max; ++i) { | |
| output = g.send(static_cast<char>(i)); | |
| if (i % 10000 == 0) { | |
| now = std::chrono::system_clock::now(); | |
| std::chrono::duration<double> elapsed = now - start; | |
| std::cout << i << ": " << 1000.0 / elapsed.count() << " SPS" | |
| << std::endl; | |
| start = now; | |
| } | |
| // std::cout << '(' << output << ')'; | |
| } | |
| } | |
| std::cout << std::endl << "All done." << std::endl; | |
| } |
This file contains hidden or 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
| // Cf. https://github.com/python/cpython/blob/2.7/Demo/threads/Generator.py | |
| #include <unistd.h> | |
| #include <cassert> | |
| #include <cstdio> | |
| #include <chrono> | |
| #include <iostream> | |
| #include <thread> | |
| int max = 4; | |
| struct Generator { | |
| Generator() { | |
| pipe(pipe_stdout); | |
| pipe(pipe_lock); | |
| out = fdopen(pipe_stdout[1], "w"); | |
| } | |
| ~Generator() { | |
| fclose(out); | |
| for (int i = 0; i < 2; ++i) { | |
| close(pipe_stdout[i]); | |
| close(pipe_lock[i]); | |
| } | |
| } | |
| std::string start() { | |
| assert(!started); | |
| started = true; | |
| return get(); | |
| } | |
| char put() { | |
| // Producer has done one step. Get one char from consumer. | |
| char c; | |
| end(); | |
| return c; | |
| } | |
| void end() { | |
| char c = '\0'; | |
| write(pipe_stdout[1], &c, 1); | |
| } | |
| std::string get() { | |
| std::string result(BUFSIZ, ' '); | |
| ssize_t size; | |
| size_t length = 0; | |
| size_t remaining = result.length(); | |
| do { | |
| if (remaining == 0) { | |
| result.resize(2 * result.length()); | |
| remaining = result.length() - length; | |
| } | |
| size = read(pipe_stdout[0], static_cast<void *>(&(result[length])), | |
| remaining); | |
| assert(size > 0); | |
| length += size; | |
| remaining -= size; | |
| } while (result[length - 1] != '\0'); | |
| result.resize(length - 1); | |
| return result; | |
| } | |
| std::string send(char c) { return get(); } | |
| int pipe_stdout[2]; | |
| int std_stdout; | |
| int pipe_lock[2]; | |
| bool started = false; | |
| FILE *out; | |
| }; | |
| void iteration(Generator *g, int i) { | |
| fprintf(g->out, " #%d >>> ", i); | |
| fprintf(g->out, "Last input: %i", i); | |
| g->end(); | |
| } | |
| int main(int argc, char **argv) { | |
| { | |
| if (argc > 1) max = std::stoi(argv[1]); | |
| Generator g; | |
| auto start = std::chrono::system_clock::now(); | |
| iteration(&g, 1); | |
| std::string output = g.start(); | |
| auto now = std::chrono::system_clock::now(); | |
| for (int i = 1; i < max; ++i) { | |
| iteration(&g, i); | |
| output = g.send(static_cast<char>(i)); | |
| if (i % 10000 == 0) { | |
| now = std::chrono::system_clock::now(); | |
| std::chrono::duration<double> elapsed = now - start; | |
| std::cout << i << ": " << 1000.0 / elapsed.count() << " SPS" | |
| << std::endl; | |
| start = now; | |
| } | |
| // std::cout << '(' << output << ')'; | |
| } | |
| } | |
| std::cout << std::endl << "All done." << std::endl; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment