पृष्ठभूमि: मैं इस खिलौना की समस्या को प्रस्तुत करके निरंतरता/कोरआउट/जेनरेटर (जिसे भी निम्नलिखित कहा जाता है) को कार्यान्वित करने का तरीका जानने का प्रयास कर रहा हूं। पर्यावरण जीसीसी 4.6 और लिनक्स 3.0 x86_64 पर सी ++ 11 है। गैर पोर्टेबल ठीक है लेकिन बाहरी पुस्तकालय का उपयोग (boost.coroutine, COROUTINE, आदि) की अनुमति नहीं है। मुझे लगता है कि longjmp(3)
और/या makecontext(2)
और मित्र मदद कर सकते हैं लेकिन सुनिश्चित नहीं हैं।सी ++/जीसीसी/लिनक्स में निरंतरता/कोरआउट/जेनरेटर
विवरण:
निम्नलिखित खिलौना पार्सर के रूप में के दृश्यों और समान लंबाई के bs पार्स करने के लिए माना जाता है। यानी
((a+)(b+))+
जैसे कि दूसरे ब्रैकेट किए गए उत्पादन की लंबाई तीसरे के बराबर होती है।
जब इसे उत्पादन मिलता है (उदाहरण के लिए aaabbb) यह a
एस की संख्या को आउटपुट करता है (उदाहरण 3)।
कोड:
#include <stdlib.h>
#include <iostream>
using namespace std;
const char* s;
void yield()
{
// TODO: no data, return from produce
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_;
// TODO: data available, continue into consume()
consume();
}
int main()
{
produce("aaab");
produce("bba");
produce("baa");
produce("aabbb");
produce("b");
// should print: 3 1 4
return 0;
}
समस्या:
आप देख सकते हैं जब yield
कहा जाता है consume
कॉल स्टैक के राज्य सहेजा जाना चाहिए और उसके बाद produce
रिटर्न। जब produce
को फिर से कॉल किया जाता है, consume
yield
से लौटकर पुनरारंभ किया जाना चाहिए। चुनौती produce
कॉल consume
पर संशोधित करने के लिए होगी, और yield
लागू करें ताकि वे इरादे के अनुसार काम कर सकें।
(। जाहिर है तो उपभोग कि यह बचत होती है और अपने राज्य अभ्यास का उद्देश्य धरा पुनर्निर्माण reimplementing)
मुझे लगता है कि क्या किया जाना चाहिए makecontext आदमी पृष्ठ के निचले भाग पर उदाहरण की तरह कुछ है: 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");
// should print: 3 1 4
return 0;
}
आपका मतलब है 'longjmp' के बारे में बहुत ज्यादा चिंता की जरूरत नहीं है? मुझे 'लांगजंप' वर्तनी वाले किसी भी फ़ंक्शन से अवगत नहीं है। –
makecontext iirc को बहिष्कृत किया गया है। –
आपको क्यों लगता है कि makecontext को बहिष्कृत किया गया है? यह मैन पेज पर इसके बारे में कुछ भी नहीं कहता है? –