Skip to content

Instantly share code, notes, and snippets.

@RossBencina
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RossBencina/4925236fa88f1a5e26ac to your computer and use it in GitHub Desktop.
Save RossBencina/4925236fa88f1a5e26ac to your computer and use it in GitHub Desktop.
// Template-based async method continuation idea by Ross Bencina <rossb@audiomulch.com> May 2014.
// see: https://groups.google.com/forum/#!topic/comp.lang.c++.moderated/ryhWI6cX3Ko
#include <iostream>
#include <list>
typedef void (*async_callback_fn_t)(void*);
struct PendingSimulatedTaskCallback{
async_callback_fn_t simulatedAsyncCallbackFn_;
void *simulatedAsyncCallbackData_;
PendingSimulatedTaskCallback( async_callback_fn_t f, void *d )
: simulatedAsyncCallbackFn_(f)
, simulatedAsyncCallbackData_(d) {}
void invokeCompletionCallback()
{
(*simulatedAsyncCallbackFn_)(simulatedAsyncCallbackData_);
}
};
std::list<PendingSimulatedTaskCallback> pendingTasks_;
void initiateSimulatedTaskWithAsyncCallback( async_callback_fn_t fn, void *data )
{
pendingTasks_.push_back(PendingSimulatedTaskCallback(fn,data));
}
bool simulatedTaskIsPending()
{
return !pendingTasks_.empty();
}
void simulateAsyncTaskCompletion()
{
PendingSimulatedTaskCallback task = pendingTasks_.front();
pendingTasks_.pop_front();
task.invokeCompletionCallback();
}
class MyAsyncMethod {
typedef MyAsyncMethod this_t;
typedef void (this_t::*asyncmethod_fn_t) ();
// async method state
int i;
int waitCount;
#define BEGIN_ASYNC_METHOD switch (PC) { case 0:;
#define AWAIT_CALLBACK_PTR &async_callback_thunk_t<&this_t::async_method_fn<__LINE__> >
#define AWAIT {return; case __LINE__:;} // MUST be on same line as call
#define WAIT_TARGET_CALLBACK_PTR(x) &async_callback_thunk_t<&this_t::async_method_fn<-x> >
#define WAIT_TARGET(x) {return; case -x:;}
#define END_ASYNC_METHOD {return; default:;} }
template< asyncmethod_fn_t F >
static void async_callback_thunk_t( void *that )
{
(static_cast<this_t*>(that)->*F)();
}
template<int PC>
void async_method_fn() {
BEGIN_ASYNC_METHOD
std::cout << "async method beginning" << std::endl;
initiateSimulatedTaskWithAsyncCallback(AWAIT_CALLBACK_PTR, this); AWAIT
std::cout << "before loop" << std::endl;
for(i=0; i < 5; ++i ){
std::cout << "in loop " << i << std::endl;
initiateSimulatedTaskWithAsyncCallback(AWAIT_CALLBACK_PTR, this); AWAIT
}
std::cout << "after loop A" << std::endl;
initiateSimulatedTaskWithAsyncCallback(AWAIT_CALLBACK_PTR, this); AWAIT
std::cout << "after loop B" << std::endl;
std::cout << "before scatter-gather" << std::endl;
waitCount = 5;
for(int i=0; i<5;++i){
initiateSimulatedTaskWithAsyncCallback(WAIT_TARGET_CALLBACK_PTR(1), this);
}
WAIT_TARGET(1)
std::cout << "received a scatter-gather callback" << std::endl;
if (--waitCount) {
return; // don't continue until all callbacks have been received
}
std::cout << "scatter-gather complete" << std::endl;
initiateSimulatedTaskWithAsyncCallback(AWAIT_CALLBACK_PTR, this); AWAIT
std::cout << "done" << std::endl;
END_ASYNC_METHOD
}
public:
void initiate()
{
async_method_fn<0>();
}
};
int main(int argc, char* argv[])
{
std::cout << "*** AsyncMethod *** " << std::endl;
MyAsyncMethod async;
async.initiate();
while (simulatedTaskIsPending())
simulateAsyncTaskCompletion();
std::cout << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment