سؤال

لا شك أنه يمكن القيام به portably ، ولكن هل هناك أي حلول هناك ؟ أعتقد أنه يمكن القيام به من خلال خلق بديل كومة الإعادة SP,بي بي, IP على إدخال الدالة ، وبعد أن العائد حفظ الملكية الفكرية واستعادة SP+BP.Destructors و استثناء السلامة تبدو صعبة ولكن قابلة للحل.

فقد تم القيام به ؟ هل هو مستحيل ؟

هل كانت مفيدة؟

المحلول

نعم يمكن القيام به من دون مشكلة.كل ما تحتاجه هو القليل من الجمعية رمز للانتقال مكدس الاستدعاءات حديثا تخصيص كومة كومة الذاكرة المؤقتة.

أود أن نظرة على دفعة::coroutine مكتبة.

الشيء الوحيد الذي يجب أن احترس من هو تجاوز سعة مكدس.على معظم أنظمة التشغيل تفيض كومة سوف يسبب segfault لأن الذاكرة الظاهرية الصفحة غير معين.ومع ذلك إذا كنت تخصيص كومة كومة كنت لا تحصل على أي ضمان.فقط الحفاظ على ذلك في الاعتبار.

نصائح أخرى

على POSIX ، يمكنك استخدام makecontext()/swapcontext() إجراءات portably التبديل التنفيذ السياقات.على ويندوز, يمكنك استخدام الألياف API.وإلا فإن كل ما تحتاجه هو القليل من الغراء الجمعية رمز تبديل الجهاز السياق.لقد نفذت coroutines سواء مع ASM (على AMD64) و مع swapcontext();ليس من الصعب جدا.

من أجل الأجيال القادمة ،

ديمتري Vyukov هو ونديفول الموقع وقد خدعة ذكية باستخدام ucontext و setjump إلى محاكاة coroutines في c++.

كما أوليفر Kowalke سياق المكتبة قبلت مؤخرا في دفعة ، لذلك نأمل أن نرى نسخة محدثة من دفعة.coroutine الذي يعمل على x86_64 قريبا.

ليس هناك طريقة سهلة لتنفيذ coroutine.لأن coroutine نفسه هو من C/C++'s كومة التجريد مثل الخيط.لذلك لا يمكن أن تكون معتمدة من دون لغة التغييرات على مستوى دعم.

حاليا(C++11) كل القائمة C++ coroutine تطبيقات على الجمعية مستوى القرصنة التي من الصعب أن تكون آمنة وموثوق بها عبور فوق المنصات.أن تكون موثوقة فإنه يحتاج إلى أن يكون معيار التعامل معها من قبل المجمعين بدلا من القرصنة.

هناك اقتراح القياسية - N3708 من أجل هذا.التحقق من ذلك إذا كنت مهتما.

قد تكون أفضل حالا مع التكرار من coroutine إذا كان ذلك ممكنا.بهذه الطريقة يمكنك الحفاظ على الدعوة next() للحصول على القيمة التالية ، ولكن يمكنك الحفاظ على جهاز الدولة كعضو المتغيرات بدلا من المتغيرات المحلية.

قد تجعل الأمور أكثر للصيانة.آخر C++ المطور قد لا يفهم على الفور coroutine في حين أنها قد تكون أكثر دراية مكرر.

بالنسبة لأولئك الذين يريدون أن يعرفوا كيف أنها قد النفوذ Coroutines في المحمولة في C++ سوف تضطر إلى الانتظار ل C++17 الانتظار أكثر (انظر أدناه)!معايير اللجنة تعمل على ميزة مشاهدة N3722 الورق.تلخيص المشروع الحالي من الورق بدلا من أن المتزامن وننتظر, الكلمات الرئيسية سوف يكون الاستئناف و انتظار.

نلقي نظرة على التجريبي التنفيذ في Visual Studio 2015 للعب مع مايكروسوفت التجريبية التنفيذ.أنها لا تبدو مثل رنة لديه التنفيذ حتى الآن.

هناك حديث جيد من Cppcon Coroutines سلبي النفقات العامة التجريد تلخيص فوائد استخدام Coroutines في C++ وكيف يؤثر البساطة والأداء من التعليمات البرمجية.

في الوقت الحاضر لا يزال لدينا لاستخدام مكتبة تطبيقات, ولكن في المستقبل القريب سيكون لدينا coroutines الأساسية C++ الميزة.

تحديث:يبدو coroutine تنفيذ المقرر عن C++20 ، ولكن أفرج عنه حسب المواصفات الفنية مع C++17 (p0057r2).Visual C++, رنة دول مجلس التعاون الخليجي تسمح لك أن تختار في استخدام وقت الترجمة العلم.

لا COROUTINE المحمولة C++ مكتبة coroutine التسلسل نقطة لكم في الاتجاه الصحيح ؟ يبدو أن الحل الأنيق الذي استمر اختبار الزمن.....إنه من العمر 9 سنوات!

في دكتور مجلد pdf من الورق المحمولة C++ مكتبة Coroutine التسلسل من Keld Helsgaun الذي يصف المكتبة توفر قصيرة أمثلة استخدامه.

[تحديث] أنا في الواقع مما يجعل الاستخدام الناجح هو نفسي.الفضول حصلت على أفضل مني ، حتى لقد نظرت إلى هذا الحل ، و وجدنا أنه كان مناسبا مشكلة لقد تم العمل على بعض الوقت!

أنا لا أعتقد أن هناك العديد من كاملة ونظيفة تطبيقات في C++.محاولة واحدة أن أحب هو آدم Dunkels' protothread المكتبة.

انظر أيضا Protothreads:تبسيط الحدث يحركها برمجة الذاكرة مقيدة النظم المضمنة في ACM المكتبة الرقمية و النقاش في ويكيبيديا الموضوع Protothread,

مكتبة جديدة ، دفعة.السياق, أصدرت اليوم مع ميزات المحمولة لتنفيذ coroutines.

هذا هو الموضوع القديم, ولكن أود أن أقترح الإختراق باستخدام داف الجهاز الذي لا التي تعتمد على نظام التشغيل (على ما أذكر):

ج coroutines باستخدام داف الجهاز

و كمثال على ذلك, هنا هو telnet المكتبة انا عدلت إلى استخدام coroutines بدلا من شوكة/المواضيع:Telnet cli المكتبة باستخدام coroutines

و منذ القياسية ج قبل C99 هو الأساس الحقيقي فرعية من C++, هذا يعمل بشكل جيد في C++ جدا.

لأنه يقوم على (تذلل) وحدات الماكرو ، ولكن الموقع التالي يوفر وسيلة سهلة لاستخدام مولد التنفيذ: http://www.codeproject.com/KB/cpp/cpp_generators.aspx

لقد جئت مع التنفيذ دون asm التعليمات البرمجية.والفكرة هي أن استخدام النظام موضوع إنشاء وظيفة تهيئة مكدس و السياق ، واستخدام setjmp/longjmp للتبديل السياق.ولكن ليس المحمولة, رؤية صعبة pthread الإصدار إذا كنت مهتما.

https://github.com/tonbit/coroutine هو C++11 واحد .ساعة غير المتماثلة coroutine تنفيذ دعم استئناف/العائد/ننتظر الأوليات و نموذج القناة.انها تنفذ عبر ucontext / الألياف ، وليس اعتمادا على دفعة تعمل على لينكس/ويندوز/ماك.انها نقطة انطلاق جيدة لتعلم تنفيذ coroutine في c++.

تحقق من بلدي التنفيذ ، فإنه يوضح asm القرصنة نقطة بسيطة:

https://github.com/user1095108/generic/blob/master/coroutine.hpp

يجب عليك أن تنظر دائما باستخدام خيوط بدلا من ذلك ؛ وخاصة في الأجهزة الحديثة.إذا كان لديك عمل يمكن أن يكون منطقيا فصل في Co-الروتين باستخدام خيوط يعني أن العمل قد يكون في الواقع في آن واحد ، منفصلة وحدات التنفيذ (المعالج النوى).

ولكن ربما كنت لا تريد استخدام coroutines ، ربما لأن لديك اختبار جيد الخوارزمية التي سبق أن كتبت واختبارها بهذه الطريقة ، أو بسبب ترقية قانون مكتوب بهذه الطريقة.

إذا كنت تعمل ضمن ويندوز ، يجب أن نلقي نظرة على الألياف.الألياف سوف تعطيك coroutine مثل إطار بدعم من نظام التشغيل.

أنا لم تكن مألوفة مع نظام التشغيل الأخرى هي أن يوصي البدائل هناك.

WvCont هو جزء من WvStreams التي تطبق ما يسمى شبه coroutines.هذه هي أسهل قليلا للتعامل مع من الكامل-على coroutines:تدعوه إلى ذلك ، فإنه ينتج العودة إلى الشخص الذي يطلق عليه.

انها تنفذ باستخدام أكثر مرونة WvTask الذي يدعم كامل على coroutines;يمكنك العثور عليه في نفس المكتبة.

يعمل على win32 و لينكس, على الأقل, وربما أي نظام يونكس.

لقد حاولت تنفيذ coroutines نفسي باستخدام C++11 و المواضيع:

#include <iostream>
#include <thread>

class InterruptedException : public std::exception {
};

class AsyncThread {
public:
    AsyncThread() {
        std::unique_lock<std::mutex> lock(mutex);
        thread.reset(new std::thread(std::bind(&AsyncThread::run, this)));
        conditionVar.wait(lock); // wait for the thread to start
    }
    ~AsyncThread() {
        {
            std::lock_guard<std::mutex> _(mutex);
            quit = true;
        }
        conditionVar.notify_all();
        thread->join();
    }
    void run() {
        try {
            yield();
            for (int i = 0; i < 7; ++i) {
                std::cout << i << std::endl;
                yield();
            }
        } catch (InterruptedException& e) {
            return;
        }
        std::lock_guard<std::mutex> lock(mutex);
        quit = true;
        conditionVar.notify_all();
    }
    void yield() {
        std::unique_lock<std::mutex> lock(mutex);
        conditionVar.notify_all();
        conditionVar.wait(lock);
        if (quit) {
            throw InterruptedException();
        }
    }
    void step() {
        std::unique_lock<std::mutex> lock(mutex);
        if (!quit) {
            conditionVar.notify_all();
            conditionVar.wait(lock);
        }
    }
private:
    std::unique_ptr<std::thread> thread;
    std::condition_variable conditionVar;
    std::mutex mutex;
    bool quit = false;
};

int main() {
    AsyncThread asyncThread;
    for (int i = 0; i < 3; ++i) {
        std::cout << "main: " << i << std::endl;
        asyncThread.step();
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top