Background: I'm trying to figure out how to implement continuations / coroutines / generators (regardless of what is called below) by putting this toy. The environment is C ++ 11 on gcc 4.6 and linux 3.0 x86_64. Not portable, but using an external library (boost.coroutine, COROUTINE, etc.) is not allowed. I think that longjmp(3)both makecontext(2)friends can help, but are not sure.
Description:
The next toy parser should analyze sequences of as and bs of equal length. i.e
((a+)(b+))+
so the length of the second bracket is the third.
When he finds a work (e.g. aaabbb), he gives out the number ahe finds (e.g. 3).
The code:
#include <stdlib.h>
#include <iostream>
using namespace std;
const char* s;
void yield()
{
abort();
}
void advance()
{
s++;
if (*s == 0)
yield();
}
void consume()
{
while (true)
{
int i = 0;
while (*s == 'a')
{
i++;
advance();
}
cout << i << " ";
while (i-- > 0)
{
if (*s != 'b')
abort();
advance();
}
}
}
void produce(const char* s_)
{
s = s_;
consume();
}
int main()
{
produce("aaab");
produce("bba");
produce("baa");
produce("aabbb");
produce("b");
return 0;
}
Problem:
, consume yield, produce. produce , consume , yield. , produce consume yield, .
(, , , .)
, , , mankontext man: http://www.kernel.org/doc/man-pages/online/pages/man3/makecontext.3.html, , . ( )
:
( )
#include <stdlib.h>
#include <iostream>
#include <ucontext.h>
using namespace std;
const char* s;
ucontext_t main_context, consume_context;
void yield()
{
swapcontext(&consume_context, &main_context);
}
void advance()
{
s++;
if (*s == 0)
yield();
}
void consume()
{
while (true)
{
int i = 0;
while (*s == 'a')
{
i++;
advance();
}
cout << i << " ";
while (i-- > 0)
{
advance();
}
}
}
void produce(const char* s_)
{
s = s_;
swapcontext(&main_context, &consume_context);
}
int main()
{
char consume_stack[4096];
getcontext(&consume_context);
consume_context.uc_stack.ss_sp = consume_stack;
consume_context.uc_stack.ss_size = sizeof(consume_stack);
makecontext(&consume_context, consume, 0);
produce("aaab");
produce("bba");
produce("baa");
produce("aabbb");
produce("b");
return 0;
}