aboutsummaryrefslogtreecommitdiff
path: root/external/glim/test_cbcoro.cc
diff options
context:
space:
mode:
Diffstat (limited to 'external/glim/test_cbcoro.cc')
-rw-r--r--external/glim/test_cbcoro.cc89
1 files changed, 89 insertions, 0 deletions
diff --git a/external/glim/test_cbcoro.cc b/external/glim/test_cbcoro.cc
new file mode 100644
index 000000000..f47cdac39
--- /dev/null
+++ b/external/glim/test_cbcoro.cc
@@ -0,0 +1,89 @@
+// http://en.wikipedia.org/wiki/Setcontext; man 3 makecontext; man 2 getcontext
+// http://www.boost.org/doc/libs/1_53_0/libs/context/doc/html/index.html
+// g++ -std=c++11 -O1 -Wall -g test_cbcoro.cc -pthread && ./a.out
+
+#include <glim/exception.hpp>
+#include <glim/NsecTimer.hpp>
+
+#include "cbcoro.hpp"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h> // sleep
+#include <string.h> // strerror
+#include <errno.h>
+#include <functional>
+using std::function;
+#include <thread>
+#include <memory>
+using std::shared_ptr; using std::make_shared;
+#include <string>
+using std::string; using std::to_string;
+#include <iostream>
+using std::cout; using std::endl;
+
+/** A typical remote service with callback. */
+void esDelete (int frople, std::function<void(int)> cb) {
+ std::thread th ([cb,frople]() {
+ cout << "esDelete: sleeping for a second" << endl;
+ std::this_thread::sleep_for (std::chrono::seconds (1));
+ cb (frople);
+ }); th.detach();
+}
+
+struct RemoveFroples: public glim::CBCoro {
+ const char* _argument;
+ RemoveFroples (const char* argument): _argument (argument) {
+ cout << "RF: constructor" << endl;
+ }
+ virtual ~RemoveFroples() {puts ("~RemoveFroples");}
+ virtual void run() override {
+ for (int i = 1; i <= 4; ++i) {
+ cout << "RF: Removing frople " << i << "..." << endl;
+ int returnedFrople = 0;
+ yieldForCallback ([this,i,&returnedFrople]() {
+ if (i != 2) {
+ // Sometimes we use a callback.
+ esDelete (i, [this,&returnedFrople](int frople) {
+ cout << "RF,CB: frople " << frople << "." << endl;
+ returnedFrople = frople;
+ invokeFromCallback();
+ });
+ } else {
+ // Sometimes we don't use a callback.
+ returnedFrople = 0;
+ invokeFromCallback();
+ }
+ });
+ cout << "RF: Returned from callback; _returnTo is: " << (intptr_t) _returnTo << "; frople " << returnedFrople << endl;
+ }
+ cout << "RF: finish! _returnTo is: " << (intptr_t) _returnTo << endl;
+ };
+};
+
+int main() {
+ glim::cbCoro ([](glim::CBCoro* cbcoro) {
+ cout << "main: run1, thread " << std::this_thread::get_id() << endl; // Runs on the `main` thread.
+ cbcoro->yieldForCallback ([&]() {
+ std::thread callbackThread ([&]() {
+ std::this_thread::sleep_for (std::chrono::seconds (4));
+ cbcoro->invokeFromCallback();
+ }); callbackThread.detach();
+ });
+ cout << "main: run2, thread " << std::this_thread::get_id() << endl; // Runs on the `callbackThread`.
+ });
+
+ (new RemoveFroples ("argument"))->start();
+ cout << "main: returned from RemoveFroples" << endl;
+
+ glim::NsecTimer timer; const int ops = RUNNING_ON_VALGRIND ? 999 : 9999;
+ for (int i = 0; i < ops; ++i) glim::cbCoro ([](glim::CBCoro* cbcoro) {});
+ double speedEmpty = ops / timer.sec();
+ timer.restart();
+ for (int i = 0; i < ops; ++i) glim::cbCoro ([](glim::CBCoro* cbcoro) {cbcoro->yieldForCallback ([&]() {cbcoro->invokeFromCallback();});});
+ double speedImmediate = ops / timer.sec();
+
+ sleep (5);
+ cout << "speed: empty: " << speedEmpty << " o/s" << endl;
+ cout << "speed: immediate: " << speedImmediate << " o/s" << endl;
+ return 0;
+}