Created
April 1, 2013 15:58
-
-
Save wilburding/5285775 to your computer and use it in GitHub Desktop.
continuation monad in c++
idea originate from https://www.fpcomplete.com/blog/2012/06/asynchronous-api-in-c-and-the-continuation-monad
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
#include <iostream> | |
#include <vector> | |
#include <string> | |
#include <mutex> | |
#include <future> | |
#include <chrono> | |
#include <utility> | |
#include <assert.h> | |
#include <pthread.h> | |
#include <unistd.h> | |
using namespace std; | |
//printf is thread-safe | |
void asyncApi(const function<void(string)>& handler, const string& s) | |
{ | |
thread th([handler, s]{ | |
printf("Started async\n"); | |
this_thread::sleep_for(chrono::seconds(3)); | |
handler(s); | |
}); | |
th.detach(); | |
} | |
template<class R, class A> | |
struct Continuator | |
{ | |
typedef function<R(const function<R(A)>&)> ActionFunc; | |
Continuator(ActionFunc f) | |
:_action(f) | |
{} | |
R andThen(const function<R(A)>& k) const | |
{ | |
return _action(k); | |
} | |
ActionFunc _action; | |
}; | |
template<class R, class A> | |
R andThen(const Continuator<R, A>& ktor, const function<R(A)>& f) | |
{ | |
return ktor.andThen(f); | |
} | |
template<class R, class A> | |
Continuator<R, A> Return(A a) | |
{ | |
return { [a](const function<R(A)>& f) { return f(a); }}; | |
} | |
template<class R, class A> | |
Continuator<R, A> Bind(const Continuator<R, A>& ktor, const function<Continuator<R, A>(A)>& rest) | |
{ | |
return { [ktor, rest](const function<R(A)>& k) | |
{ | |
auto lambda = [k, rest](A a) { | |
return rest(a).andThen(k); | |
}; | |
return ktor.andThen(lambda); | |
} | |
}; | |
} | |
Continuator<void, string> Async(const string& s) | |
{ | |
return { | |
[s](const function<void(string)>& f) { | |
asyncApi(f, s); | |
} | |
}; | |
} | |
Continuator<void, string> loop(string s) | |
{ | |
return { | |
[s](const function<void(string)>& f) { | |
printf("In loop %s\n", s.c_str()); | |
Bind<void, string>(Async(s), loop).andThen(f); | |
} | |
}; | |
} | |
Continuator<void, string> loop_n(string s, int n) | |
{ | |
if(n == 0) | |
{ | |
return Return<void, string>(s); | |
} | |
else | |
{ | |
return { | |
[n, s](const function<void(string)>& f){ | |
printf("in loop %d: %s\n", n, s.c_str()); | |
Bind<void, string>(Async(s.substr(0, s.size() - 1)), bind(loop_n, placeholders::_1, n - 1)).andThen(f); | |
} | |
}; | |
} | |
} | |
int main(int argc, char* argv[]) | |
{ | |
/*andThen<void, string>(ktor, [](string s) { cout << "worker: " << s << endl;});*/ | |
/*loop("blah").andThen([](string s) { cout << "never" << endl; });*/ | |
loop_n("blahblahblah", 5).andThen([](string s) { printf("done: %s\n", s.c_str()); }); | |
for(int i = 0; i < 20; ++i) | |
{ | |
cout << i << endl; | |
this_thread::sleep_for(chrono::seconds(1)); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment