روتين فرعي
الروتينات الفرعية هي مكونات برمجية يمكن إيقافها واستئنافها - وهي عبارة عن روتينات فرعية عامة - لتنفيذ مهام متعددة تعاونية . وتُعدّ الروتينات الفرعية مناسبة تمامًا لتنفيذ مكونات برمجية مألوفة مثل المهام التعاونية ، والاستثناءات ، وحلقات الأحداث ، والمكررات ، والقوائم اللانهائية ، والأنابيب .
وقد وُصفت بأنها "وظائف يمكنك إيقاف تنفيذها مؤقتًا". [ 1 ]
صاغ ميلفين كونواي مصطلح "الروتين الفرعي" في عام 1958 عندما طبقه على بناء برنامج تجميع . [ 2 ] ظهر أول شرح منشور للروتين الفرعي لاحقًا، في عام 1963. [ 3 ]
التعريف والأنواع
لا يوجد تعريف دقيق واحد للروتين المشترك. في عام 1980، لخص كريستوفر د. مارلين [ 4 ] سمتين أساسيتين معترف بهما على نطاق واسع للروتين المشترك:
- تستمر قيم البيانات المحلية للروتين الفرعي بين الاستدعاءات المتتالية؛
- يتم تعليق تنفيذ الروتين الفرعي عند مغادرة التحكم له، فقط لاستئنافه من حيث توقف عندما يعود التحكم إلى الروتين الفرعي في مرحلة لاحقة.
إلى جانب ذلك، يتميز تطبيق الروتين الفرعي بثلاث خصائص:
- آلية نقل التحكم. عادةً ما توفر الروتينات الفرعية غير المتماثلة
yieldكلمات مفتاحية مثل `return` و`return`resume. لا يستطيع المبرمجون اختيار الإطار الذي سيتم التنازل إليه بحرية، حيث يتم التنازل فقط إلى أقرب مُستدعي للروتين الفرعي الحالي. من ناحية أخرى، في الروتينات الفرعية المتماثلة ، يجب على المبرمجين تحديد وجهة التنازل. - سواء تم توفير الروتينات الفرعية في اللغة ككائنات من الدرجة الأولى ، والتي يمكن للمبرمج التلاعب بها بحرية، أو كبنى مقيدة؛
- ما إذا كان بإمكان روتين فرعي إيقاف تنفيذه مؤقتًا من داخل استدعاءات الدوال المتداخلة. يُسمى هذا الروتين الفرعي بروتين فرعي مُكدس . أما الروتين الفرعي المُخالف فيُسمى روتين فرعي غير مُكدس ، حيث لا يُمكن للدالة العادية استخدام الكلمة المفتاحية `stackful` إلا إذا تم تحديده كروتين فرعي
yield.
اقترحت ورقة بحثية بعنوان "إعادة النظر في الروتينات الفرعية" [ 5 ] ، نُشرت عام 2009، مصطلح " الروتين الفرعي الكامل" للدلالة على الروتين الفرعي الذي يدعم الروتينات الفرعية من الدرجة الأولى ويكون ذا مكدس كامل. تستحق الروتينات الفرعية الكاملة اسمها الخاص نظرًا لقدرتها التعبيرية المماثلة للاستمراريات أحادية التنفيذ والاستمراريات المحددة. تكون الروتينات الفرعية الكاملة إما متناظرة أو غير متناظرة. ومن المهم الإشارة إلى أن كون الروتين الفرعي متناظرًا أو غير متناظر لا يؤثر على قدرته التعبيرية، مع أن الروتينات الفرعية الكاملة أكثر تعبيرية من الروتينات الفرعية غير الكاملة. وبينما تتساوى قدرتها التعبيرية، فإن الروتينات الفرعية غير المتناظرة تُشبه إلى حد كبير هياكل التحكم القائمة على الروتينات، حيث يُعاد التحكم دائمًا إلى المُستدعي، وهو ما قد يكون مألوفًا أكثر للمبرمجين.
المقارنات
البرامج الفرعية
الروتينات الفرعية هي حالات خاصة من الروتينات المتزامنة. [ 6 ] عند استدعاء الروتينات الفرعية، يبدأ التنفيذ من البداية، وبمجرد خروج الروتين الفرعي، ينتهي عمله؛ إذ لا تعود نسخة الروتين الفرعي إلا مرة واحدة، ولا تحتفظ بأي حالة بين الاستدعاءات. على النقيض من ذلك، يمكن للروتينات المتزامنة الخروج عن طريق استدعاء روتينات متزامنة أخرى، والتي قد تعود لاحقًا إلى النقطة التي تم استدعاؤها منها في الروتين المتزامن الأصلي؛ من وجهة نظر الروتين المتزامن، فهو لا يخرج بل يستدعي روتينًا متزامنًا آخر. [ 6 ] وبالتالي، تحتفظ نسخة الروتين المتزامن بحالة، وتتغير بين الاستدعاءات؛ ويمكن أن يكون هناك عدة نسخ من روتين متزامن معين في وقت واحد. الفرق بين استدعاء روتين متزامن آخر عن طريق "التنازل" له واستدعاء روتين آخر ببساطة (والذي سيعود بدوره إلى النقطة الأصلية)، هو أن العلاقة بين روتينين متزامنين يتنازلان لبعضهما البعض ليست علاقة المستدعي والمستدعى، بل هي علاقة متناظرة.
يمكن ترجمة أي روتين فرعي إلى روتين فرعي لا يستدعي yield . [ 7 ]
إليك مثال بسيط يوضح فائدة الروتينات الفرعية. لنفترض أن لديك علاقة بين مُنتِج ومُستهلِك، حيث يقوم روتين بإنشاء عناصر وإضافتها إلى قائمة انتظار، بينما يقوم روتين آخر بإزالة عناصر من قائمة الانتظار واستخدامها. ولأسباب تتعلق بالكفاءة، تريد إضافة وإزالة عدة عناصر في آنٍ واحد. قد يبدو الكود كالتالي:
q : = new Queue <Item>تقوم الدالة الفرعية بإنشاء حلقة طالما أن قائمة الانتظار ليست ممتلئة أنشئ بعض العناصر الجديدة أضف العناصر إلى q الاستسلام للاستهلاك حلقة استهلاك الروتين الفرعي طالما أن q غير فارغة قم بإزالة بعض العناصر من قائمة الانتظار q استخدم العناصر يؤدي إلى الإنتاج منتج الاتصال
يتم ملء قائمة الانتظار أو تفريغها بالكامل قبل تسليم التحكم إلى الروتين الفرعي الآخر باستخدام الأمر yield . تبدأ استدعاءات الروتينات الفرعية اللاحقة مباشرةً بعد الأمر yield ، في حلقة الروتين الفرعي الخارجية.
على الرغم من أن هذا المثال يستخدم غالبًا كمقدمة للتعددية الخيطية ، إلا أنه لا حاجة إلى خيطين لهذا الغرض: يمكن تنفيذ عبارة yield عن طريق القفز مباشرة من روتين إلى آخر.
الخيوط
تتشابه الروتينات الفرعية إلى حد كبير مع الخيوط . إلا أن الروتينات الفرعية تُنفذ مهامًا متعددة بشكل تعاوني ، بينما تُنفذ الخيوط عادةً مهامًا متعددة بشكل استباقي . توفر الروتينات الفرعية التزامن ، لأنها تسمح بتنفيذ المهام خارج الترتيب أو بترتيب قابل للتغيير، دون التأثير على النتيجة النهائية، لكنها لا توفر التوازي ، لأنها لا تُنفذ مهامًا متعددة في وقت واحد. من مزايا الروتينات الفرعية على الخيوط أنه يمكن استخدامها في سياق الوقت الحقيقي الصارم ( لا يتطلب التبديل بين الروتينات الفرعية أي استدعاءات نظام أو أي استدعاءات حظر على الإطلاق)، ولا حاجة إلى أدوات التزامن الأساسية مثل المؤشرات المتبادلة والإشارات، وما إلى ذلك، لحماية المقاطع الحرجة ، كما أنها لا تتطلب دعمًا من نظام التشغيل.
من الممكن تنفيذ الروتينات الفرعية باستخدام الخيوط المجدولة مسبقًا، بطريقة ستكون شفافة بالنسبة للتعليمات البرمجية المستدعِية، ولكن بعض المزايا (وخاصة ملاءمتها للتشغيل في الوقت الحقيقي الصارم وانخفاض تكلفة التبديل بينها نسبيًا) ستضيع.
مولدات كهربائية
المولدات، والمعروفة أيضًا باسم شبه الروتينات، [ 8 ] هي مجموعة فرعية من الروتينات. على وجه التحديد، بينما يمكن لكليهما التوقف مؤقتًا عدة مرات، مما يسمح بإعادة الدخول من نقاط دخول متعددة، إلا أنهما يختلفان في قدرة الروتينات على التحكم في مكان استمرار التنفيذ مباشرةً بعد التوقف المؤقت، بينما لا تستطيع المولدات ذلك، بل تعيد التحكم إلى مُستدعي المولد. [ 9 ] أي، بما أن المولدات تُستخدم في المقام الأول لتبسيط كتابة المُكرِّرات ، فإن yieldالعبارة في المولد لا تُحدد روتينًا للقفز إليه، بل تُمرر قيمة إلى روتين رئيسي.
ومع ذلك، لا يزال من الممكن تنفيذ الروتينات الفرعية على وحدة توليد، بمساعدة روتين إرسال عالي المستوى ( ترامبولين ، بشكل أساسي) يقوم بتمرير التحكم بشكل صريح إلى المولدات الفرعية المحددة بواسطة الرموز المميزة التي يتم إرجاعها من المولدات:
q : = new Queue <Item>يقوم المولد بإنتاج حلقة تكرارية طالما أن q غير ممتلئ أنشئ بعض العناصر الجديدة أضف العناصر إلى q أَثْمَرحلقة استهلاك المولد طالما أن q غير فارغة قم بإزالة بعض العناصر من قائمة الانتظار q استخدم العناصر أَثْمَرمُوزِّع الروتينات الفرعية d := new Map < Generator , Iterator > d[produce] := start consume d[consume] := start produce الحالي := إنتاج مكالمة متكررة حالية current := next d[current] موظف استقبال المكالمات
يستخدم عدد من تطبيقات الروتينات الفرعية للغات التي تدعم المولدات ولكن ليس لديها روتينات فرعية أصلية (مثل بايثون [ 10 ] قبل 2.5) هذا النموذج أو نموذجًا مشابهًا.
التكرار المتبادل
يُشبه استخدام الروتينات الفرعية لآلات الحالة أو التزامن استخدام الاستدعاءات المتكررة مع استدعاءات الذيل ، حيث ينتقل التحكم في كلتا الحالتين إلى روتين فرعي مختلف ضمن مجموعة من الروتينات. مع ذلك، تتميز الروتينات الفرعية بمرونة أكبر وكفاءة أعلى عمومًا. ولأنها تُنفذ عملية التنازل بدلًا من الإرجاع، ثم تستأنف التنفيذ بدلًا من البدء من جديد، فإنها قادرة على الاحتفاظ بالحالة، سواءً المتغيرات (كما في الإغلاق) أو نقطة التنفيذ، ولا يقتصر التنازل على موقع الذيل؛ إذ يجب على الروتينات الفرعية المتكررة استخدام متغيرات مشتركة أو تمرير الحالة كمعاملات. علاوة على ذلك، يتطلب كل استدعاء متكرر لروتين فرعي إطار مكدس جديد (إلا إذا تم تطبيق حذف استدعاءات الذيل )، بينما يستخدم تمرير التحكم بين الروتينات الفرعية السياقات الموجودة ويمكن تنفيذه ببساطة عن طريق القفز.
الاستخدامات الشائعة
تُعدّ الروتينات الفرعية مفيدة لتنفيذ ما يلي:
- آلات الحالة داخل روتين فرعي واحد، حيث يتم تحديد الحالة من خلال نقطة الدخول/الخروج الحالية للإجراء؛ يمكن أن يؤدي هذا إلى كود أكثر قابلية للقراءة مقارنة باستخدام goto ، ويمكن أيضًا تنفيذه عن طريق الاستدعاء المتبادل مع استدعاءات الذيل .
- نموذج الممثل للتزامن، على سبيل المثال في ألعاب الفيديو . كل ممثل لديه إجراءاته الخاصة (وهذا يفصل الكود منطقيًا مرة أخرى)، لكنهم يتخلون طواعية عن التحكم إلى المجدول المركزي، الذي ينفذها بالتسلسل (هذا شكل من أشكال تعدد المهام التعاوني ).
- المولدات ، وهذه مفيدة للتدفقات - وخاصة الإدخال/الإخراج - وللاجتياز العام لهياكل البيانات.
- تُتيح هذه التقنية التواصل بين العمليات المتسلسلة، حيث تُمثل كل عملية فرعية روتينًا فرعيًا. وتُنتج مدخلات/مخرجات القنوات وعمليات الحظر روتينات فرعية، ويقوم مُجدول العمليات بإلغاء حظرها عند اكتمالها. وبدلاً من ذلك، قد تكون كل عملية فرعية هي العملية الأصلية للعملية التي تليها في مسار البيانات (أو التي تسبقها، وفي هذه الحالة يُمكن التعبير عن النمط باستخدام مولدات متداخلة).
- الاتصال العكسي، الذي يستخدم عادة في البرامج الرياضية، حيث يحتاج إجراء مثل الحل، أو مُقيِّم التكامل، ... إلى عملية الاستخدام لإجراء عملية حسابية، مثل تقييم معادلة أو دالة تكامل.
الدعم الأصلي
نشأت الكوروتينات كطريقة في لغة التجميع ، ولكنها مدعومة في بعض لغات البرمجة عالية المستوى .
- أيكيدو
- أنجيل سكريبت
- راقصة باليه
- بي سي بي إل
- باسكال (بورلاند توربو باسكال 7.0 مع وحدة uThreads)
- بيتا
- النعيم
- لغة C++ (منذ C++20)
- لغة سي شارب (منذ الإصدار 2.0)
- كنيسة صغيرة
- تشاك
- CLU
- د
- ديناميكية C
- إرلانغ
- فا#
- عامل
- برنامج GameMonkey النصي
- GDScript (لغة البرمجة النصية الخاصة بـ Godot)
- هاسكل [ 11 ] [ 12 ]
- التجميع عالي المستوى [ 13 ]
- رمز
- Io
- JavaScript (منذ الإصدار 1.7، تم توحيدها في ECMAScript 6) [ 14 ] يتضمن ECMAScript 2017 أيضًا دعم await .
- جوليا [ 15 ]
- Kotlin (منذ الإصدار 1.1) [ 16 ]
- ليمبو
- Lua [ 17 ]
- واضح
- μC++
- مودولا-2
- نيميرل
- بيرل 5 (باستخدام وحدة Coro )
- PHP (منذ الإصدار 5.5)
- بيكوليس
- مقدمة
- بايثون (منذ الإصدار 2.5، [ 18 ] مع دعم محسّن منذ الإصدار 3.3 ومع بناء جملة صريح منذ الإصدار 3.5 [ 19 ] )
- مضرب
- راكو [ 20 ]
- روبي
- ساذر
- مخطط
- الذات
- Simula 67 [ 21 ]
- أحاديث قصيرة
- السنجاب
- بايثون بدون مكدس
- سوبر كوليدر [ 22 ]
- Tcl (منذ الإصدار 8.6)
- أوربيسكريبت
لا تدعم لغة جافاkotlinx.coroutines الروتينات الفرعية بشكل أصلي أو من خلال المكتبات، ولكن يمكنها استدعاء روتينات كوتلن الفرعية (على الرغم من أن هذا ليس مثاليًا وسيتطلب غلاف جافا فوق كوتلن).
بما أنه يمكن استخدام الاستمراريات لتنفيذ الروتينات الفرعية، فإن لغات البرمجة التي تدعمها يمكنها أيضًا دعم الروتينات الفرعية بسهولة تامة.
التطبيقات
اعتبارًا من عام 2003لا تدعم العديد من لغات البرمجة الشائعة، بما فيها لغة C ومشتقاتها، الدوال الفرعية المدمجة (coroutines) ضمن اللغة نفسها أو مكتباتها القياسية. ويعود ذلك، في جزء كبير منه، إلى قيود تنفيذ الدوال الفرعية القائمة على المكدس . ويُستثنى من ذلك مكتبة Boost.Context في لغة C++ ، وهي جزء من مكتبة Boost ، التي تدعم تبديل السياق على معالجات ARM وMIPS وPowerPC وSPARC وx86 على أنظمة POSIX وMac OS X وWindows. ويمكن بناء الدوال الفرعية باستخدام Boost.Context.
في الحالات التي يكون فيها استخدام روتين فرعي هو التنفيذ الأمثل لآلية معينة، ولكنه غير متاح، يكون الحل المعتاد هو استخدام دالة مغلقة (closure ) - وهي روتين فرعي يحتوي على متغيرات حالة ( متغيرات ثابتة ، غالبًا ما تكون علامات منطقية) للحفاظ على حالة داخلية بين الاستدعاءات، ونقل التحكم إلى النقطة الصحيحة. تؤدي الشروط داخل الكود إلى تنفيذ مسارات برمجية مختلفة في الاستدعاءات المتتالية، بناءً على قيم متغيرات الحالة. وهناك حل شائع آخر يتمثل في تنفيذ آلة حالة صريحة على شكل عبارة switch كبيرة ومعقدة أو عبر عبارة goto ، وخاصةً عبارة goto المحسوبة . تُعتبر هذه التطبيقات صعبة الفهم والصيانة، وهذا ما يحفز دعم الروتينات الفرعية.
تُعدّ الخيوط ، وإلى حدٍّ أقلّ الألياف ، بديلاً للروتينات الفرعية في بيئات البرمجة الشائعة اليوم. توفّر الخيوط إمكانيات لإدارة التفاعل التعاوني في الوقت الحقيقي لأجزاء التعليمات البرمجية التي تُنفّذ في آنٍ واحد . الخيوط متاحة على نطاق واسع في البيئات التي تدعم لغة C (وهي مدعومة أصلاً في العديد من اللغات الحديثة الأخرى)، وهي مألوفة لدى العديد من المبرمجين، وعادةً ما تكون مُنفّذة وموثّقة ومدعومة بشكلٍ جيّد. مع ذلك، ولأنّها تُعالج مشكلة كبيرة ومعقدة، فإنّها تتضمّن العديد من الإمكانيات القوية والمعقدة، وبالتالي تتطلّب منحنى تعلّم صعباً. لذلك، عندما يكون الروتين الفرعي هو كلّ ما هو مطلوب، قد يكون استخدام الخيط مبالغةً.
يتمثل أحد الفروق المهمة بين الخيوط والوظائف الفرعية في أن الخيوط تُجدول عادةً بشكل استباقي، بينما لا تُجدول الوظائف الفرعية كذلك. ولأن الخيوط قابلة لإعادة الجدولة في أي لحظة ويمكن تنفيذها بشكل متزامن، يجب على البرامج التي تستخدم الخيوط توخي الحذر بشأن التأمين . في المقابل، ولأن الوظائف الفرعية لا يمكن إعادة جدولتها إلا في نقاط محددة من البرنامج ولا تُنفذ بشكل متزامن، يمكن للبرامج التي تستخدمها تجنب التأمين تمامًا في كثير من الأحيان. تُذكر هذه الخاصية أيضًا كميزة للبرمجة الموجهة بالأحداث أو البرمجة غير المتزامنة.
بما أن الألياف تُجدول بشكل تعاوني، فإنها توفر أساسًا مثاليًا لتنفيذ الروتينات الفرعية المذكورة أعلاه. [ 23 ] ومع ذلك، غالبًا ما يكون دعم النظام للألياف ضعيفًا مقارنةً بدعمه للخيوط.
لغات التجميع
غالبًا ما توفر لغات التجميع المعتمدة على الجهاز طرقًا مباشرة لتنفيذ الروتينات الفرعية. على سبيل المثال، في لغة التجميع MACRO-11 ، الخاصة بعائلة الحواسيب الصغيرة PDP-11 ، يتم تنفيذ تبديل الروتين الفرعي "الكلاسيكي" بواسطة التعليمة "JSR PC,@(SP)+"، التي تقفز إلى العنوان الذي تم سحبه من المكدس وتدفع عنوان التعليمة الحالية ( أي عنوان التعليمة التالية ) إلى المكدس. في VAXen (في VAX MACRO )، تكون التعليمة المقابلة هي "JSB @(SP)+". حتى في Motorola 6809، توجد التعليمة "JSR [,S++]"؛ لاحظ "++"، حيث يتم سحب بايتين (من العنوان) من المكدس. تُستخدم هذه التعليمة بكثرة في جهاز المراقبة القياسي Assist 09.
ج
لتنفيذ الروتينات الفرعية العامة، يجب الحصول على مكدس استدعاءات ثانٍ ، وهي ميزة لا تدعمها لغة C بشكل مباشر . إحدى الطرق الموثوقة (وإن كانت خاصة بمنصة معينة) لتحقيق ذلك هي استخدام قدر ضئيل من لغة التجميع المضمنة لمعالجة مؤشر المكدس بشكل صريح أثناء الإنشاء الأولي للروتين الفرعي. هذا هو النهج الذي أوصى به توم داف في مناقشة حول مزاياه النسبية مقارنةً بالطريقة المستخدمة في Protothreads . [ 24 ] على المنصات التي توفر استدعاء النظام POSIX sigaltstack ، يمكن الحصول على مكدس استدعاءات ثانٍ عن طريق استدعاء دالة springboard من داخل معالج الإشارة [ 25 ] [ 26 ] لتحقيق الهدف نفسه في لغة C المحمولة، على حساب بعض التعقيد الإضافي. وفرت مكتبات C المتوافقة مع POSIX أو مواصفات يونكس الموحدة (SUSv3) إجراءات مثل getcontext وsetcontext وmakecontext وswapcontext ، ولكن تم إعلان هذه الدوال قديمة في POSIX 1.2008. [ 27 ]
بمجرد الحصول على مكدس استدعاء ثانٍ باستخدام إحدى الطرق المذكورة أعلاه، يمكن استخدام دالتي setjmp و longjmp في مكتبة C القياسية لتنفيذ عمليات التبديل بين الروتينات الفرعية. تحفظ هاتان الدالتان مؤشر المكدس ، وعداد البرنامج ، والسجلات المحفوظة بواسطة الدالة المستدعاة، وأي حالة داخلية أخرى حسب متطلبات واجهة التطبيق الثنائية (ABI) ، وتستعيدانها على التوالي. وبالتالي، فإن العودة إلى روتين فرعي بعد تنفيذ عملية التنازل تستعيد جميع الحالات التي كان من المفترض استعادتها عند العودة من استدعاء دالة. يمكن للتطبيقات المبسطة، التي لا تعتمد على دالتي setjmp و longjmp، تحقيق النتيجة نفسها عبر كتلة صغيرة من لغة التجميع المضمنة التي تبدل فقط مؤشر المكدس وعداد البرنامج، وتستبدل جميع السجلات الأخرى. قد يكون هذا أسرع بكثير، لأن دالتي setjmp و longjmp يجب أن تخزنا جميع السجلات التي قد تكون قيد الاستخدام وفقًا لواجهة التطبيق الثنائية (ABI)، بينما تسمح طريقة الاستبدال للمترجم بتخزين (عن طريق التخزين المؤقت في المكدس) فقط ما يعرف أنه قيد الاستخدام فعليًا.
نظراً لقلة الدعم اللغوي المباشر، قام العديد من المطورين بكتابة مكتباتهم الخاصة للروتينات الفرعية، والتي تُخفي التفاصيل المذكورة أعلاه. تُعد مكتبة libtask لروس كوكس [ 28 ] مثالاً جيداً على هذا النوع من المكتبات. فهي تستخدم دوال السياق إذا كانت متوفرة في مكتبة C الأصلية؛ وإلا فإنها توفر تطبيقاتها الخاصة لأنظمة ARM وPowerPC وSparc وx86. ومن التطبيقات البارزة الأخرى: libpcl [ 29 ] ، وcoro [ 30 ]، وlthread [ 31 ] ، وlibCoroutine [32]، و libconcurrency [33]، و libcoro [ 34]، و ribs2 [ 35 ]، و libdill [ 36 ] ، و libaco [ 37 ] ، و libco [ 26 ] .
إضافةً إلى المنهج العام المذكور أعلاه، بُذلت عدة محاولات لتقريب الدوال الفرعية في لغة C باستخدام توليفات من الدوال الفرعية ووحدات الماكرو. تُعدّ مساهمة سيمون تاتام ، [ 38 ] والمبنية على جهاز داف ، مثالًا بارزًا على هذا النوع، وهي الأساس لـ Protothreads والتطبيقات المشابهة. [ 39 ] إضافةً إلى اعتراضات داف، [ 24 ] تُقدّم تعليقات تاتام نفسه تقييمًا صريحًا لقيود هذا المنهج: "على حد علمي، هذه أسوأ محاولة اختراق برمجية بلغة C رأيتها في كود إنتاج جاد." [ 38 ] تتمثل أوجه القصور الرئيسية لهذا التقريب في أنه، لعدم الاحتفاظ بإطار مكدس منفصل لكل دالة فرعية، لا يتم الحفاظ على المتغيرات المحلية عبر عمليات الإرجاع من الدالة، ولا يمكن وجود مداخل متعددة للدالة، ولا يمكن التنازل عن التحكم إلا من الدالة الرئيسية. [ 24 ]
لغة سي++
قدمت لغة C++20 الدوال الفرعية القياسية كدوال لا تعتمد على المكدس، ويمكن تعليقها أثناء التنفيذ واستئنافها لاحقًا. تُخزن حالة التعليق للدالة الفرعية في الذاكرة الديناميكية (heap). [ 40 ] لا يزال تطبيق هذا المعيار جاريًا، حيث يدعم مُجمّعا G++ وMSVC حاليًا الدوال الفرعية القياسية بشكل كامل في الإصدارات الحديثة. [ 41 ] أُضيفت فئة مولدة للنطاقات المتزامنة والمُقيّمة عند الطلب في C++23. [ 42 ] أُضيفت فئة مهمة مناسبة في C ++26 . [ 43 ] يتم استدعاؤها باستخدام ، والتي تُرجع . [ 44 ]std::generator<Ref, V, Alloc>std::execution::task<T, Env>std::execution::sync_wait()std::optional<std::tuple<Ts...>>
هذا مثال على الروتينات الفرعية C++20 مع std::execution::task<T, Env>فئة C++26.
استيراد std ؛باستخدام std :: optional ؛ باستخدام std :: tuple ؛ باستخدام std :: execution :: task ؛task <int> add ( int a , int b ) noexcept { co_return a + b ; }task <int> test () { int ret = co_await add ( 1 , 2 ) ; std :: println ( "Return {}" , ret ) ; co_return ret ; }int main ( int argc , char * argv []) { optional < tuple < int >> result = std :: execution :: sync_wait ( test ()); std :: println ( "النتيجة: {}" , std :: get < 0 > ( result ). value_or ( std :: make_tuple ( -1 )));return 0 ; }سي شارب
أضافت لغة C# 2.0 وظيفة شبه الروتينية ( المولدات ) من خلال نمط التكرار والكلمة yieldالمفتاحية. [ 45 ] [ 46 ] وتتضمن لغة C# 5.0 دعمًا لصيغة await .
كلوجر
Cloroutine هي مكتبة خارجية توفر دعمًا للروتينات الفرعية غير المرتبطة بالمكدس في Clojure . يتم تنفيذها كوحدة ماكرو، حيث تقوم بتقسيم كتلة التعليمات البرمجية بشكل ثابت عند استدعاء المتغيرات، ثم تُصدر الروتين الفرعي كدالة ذات حالة.
د
تُنفذ D الروتينات الفرعية كفئة مكتبة قياسية core.thread.Fiberللألياف . [ 47 ] مولد ( ) [ 48 ] يجعل من السهل عرض دالة الألياف كمدخل نطاق ( ) [ 49 ] ، مما يجعل أي ألياف متوافقة مع خوارزميات النطاق الحالية.std.concurrency.Generatorstd.range.interfaces.InputRange
يذهب
تتضمن لغة Go مفهومًا مُدمجًا يُسمى " الروتينات الفرعية " (goroutines)، وهي نوع من الخيوط الخضراء ، عبارة عن عمليات خفيفة الوزن ومستقلة تُدار بواسطة بيئة تشغيل Go. يُمكن بدء روتين فرعي جديد باستخدام الكلمة المفتاحية "go". لكل روتين فرعي مكدس متغير الحجم يُمكن توسيعه حسب الحاجة. تتواصل الروتينات الفرعية عمومًا باستخدام قنوات Go المُدمجة. [ 50 ] [ 51 ] [ 52 ] [ 53 ] مع ذلك، فإن الروتينات الفرعية ليست روتينات متزامنة (على سبيل المثال، لا يتم الاحتفاظ بالبيانات المحلية بين الاستدعاءات المتتالية). [ 54 ]
جافا
توجد عدة تطبيقات للروتينات الفرعية في جافا . ورغم القيود التي تفرضها تجريدات جافا، فإن آلة جافا الافتراضية (JVM) لا تستبعد هذه الإمكانية. [ 55 ] هناك أربع طرق عامة مستخدمة، لكن اثنتين منها تُخلّان بتوافقية نقل التعليمات البرمجية بين آلات جافا الافتراضية المتوافقة مع المعايير.
- آلات جافا الافتراضية المعدلة. من الممكن إنشاء آلة جافا افتراضية مُعدّلة لدعم العمليات الفرعية بشكل أكثر أصالة. وقد تم إنشاء تصحيحات لآلة جافا الافتراضية Da Vinci . [ 56 ]
- بايت كود مُعدَّل. يمكن تفعيل وظائف الكوروتين عن طريق إعادة كتابة بايت كود جافا العادي، إما أثناء التشغيل أو أثناء الترجمة. تتضمن مجموعات الأدوات Javaflow و Java Coroutines و Coroutines .
- آليات JNI الخاصة بالمنصة. تستخدم هذه الآليات أساليب JNI المُطبقة في مكتبات نظام التشغيل أو لغة C لتوفير الوظائف لآلة JVM الافتراضية.
- تجريدات الخيوط. قد تكون مكتبات الروتينات الفرعية التي يتم تنفيذها باستخدام الخيوط ثقيلة الوزن، على الرغم من أن الأداء سيختلف بناءً على تنفيذ الخيوط في JVM.
- يمكن استدعاء الكوروتينات في Kotlin من Java، ولكن بما أن Java لا يمكنها "
suspend"، فيجب بدلاً من ذلك حظر استخدامkotlinx.coroutines.runBlocking، أو كشف واجهة برمجة تطبيقاتkotlinx.coroutines.CoroutineScopeأوkotlinx.coroutines.Job، أو (الأكثر شيوعًا) إرجاعjava.util.concurrent.CompletableFuture.
جافا سكريبت
منذ إصدار ECMAScript 2015 ، أصبح لدى JavaScript دعم للمولدات ، وهي حالة خاصة من الروتينات الفرعية. [ 57 ]
كوتلين
تُنفذ لغة Kotlin الروتينات الفرعية كجزء من مكتبة الطرف الأول.
استيراد kotlinx.coroutines.*fun main () = runBlocking { launch { delay ( 1000L ) print ( "مرحباً من داخل الروتين الفرعي!" ) }print ( "Hello world!" ) }لغة لوا
تدعم لغة Lua الروتينات الفرعية غير المتماثلة ذات المكدس من الدرجة الأولى منذ الإصدار 5.0 (2003)، [ 58 ] في مكتبة الروتينات الفرعية القياسية . [ 59 ] [ 60 ]
مودولا-2
تقوم لغة Modula-2 كما حددها ويرث بتنفيذ الروتينات الفرعية كجزء من مكتبة النظام القياسية.
يقوم الإجراء NEWPROCESS() بملء سياق معين مع إعطاء كتلة التعليمات البرمجية ومساحة للمكدس كمعاملات، ويقوم الإجراء TRANSFER() بنقل التحكم إلى روتين فرعي مع إعطاء سياق الروتين الفرعي كمعامل له.
كثرة الوحيدات
يدعم وقت تشغيل لغة Mono المشتركة الاستمراريات، [ 61 ] والتي يمكن من خلالها بناء الروتينات الفرعية.
إطار عمل .NET
أثناء تطوير إطار عمل .NET 2.0، وسّعت مايكروسوفت تصميم واجهات برمجة تطبيقات الاستضافة الخاصة بوقت تشغيل اللغة المشتركة (CLR) للتعامل مع جدولة الألياف، مع التركيز على استخدامها في وضع الألياف لخادم SQL. [ 62 ]ICLRTask::SwitchOut قبل الإصدار، أُزيل دعم خطاف تبديل المهام بسبب ضيق الوقت. [ 63 ] ونتيجةً لذلك، فإن استخدام واجهة برمجة تطبيقات الألياف لتبديل المهام ليس خيارًا عمليًا في إطار عمل .NET حاليًا.
أوكاميل
يدعم OCaml العمليات الفرعية (coroutines) من خلال وحدته Threadالنمطية. [ 64 ] توفر هذه العمليات الفرعية التزامن دون التوازي، ويتم جدولتها مسبقًا على خيط واحد من خيوط نظام التشغيل. منذ إصدار OCaml 5.0، أصبحت الخيوط الخضراء (green threads) متاحة أيضًا؛ ويتم توفيرها بواسطة وحدات نمطية مختلفة.
بيرل
يتم تنفيذ الروتينات الفرعية بشكل أصلي في جميع واجهات Raku الخلفية. [ 65 ]
PHP
بايثون
يدعم بايثونasyncio.create_task() الروتينات الفرعية باستخدام الدالة. [ 66 ]
- يوفر الإصدار 2.5 من بايثون دعمًا أفضل للوظائف الشبيهة بالروتينات الفرعية، استنادًا إلى المولدات الموسعة ( PEP 342 ).
- يعمل الإصدار 3.3 من بايثون على تحسين هذه القدرة، من خلال دعم التفويض إلى مولد فرعي ( PEP 380 ).
- يُقدّم بايثون 3.4 إطار عمل شامل للإدخال/الإخراج غير المتزامن كما هو مُوحّد في PEP 3156 ، والذي يتضمن روتينات فرعية تستفيد من تفويض المولدات الفرعية
- يقدم بايثون 3.5 دعمًا صريحًا للروتينات الفرعية باستخدام بناء الجملة async/ await ( PEP 0492 ).
- منذ إصدار بايثون 3.7، أصبحت الكلمات async/await كلمات محجوزة. [ 67 ]
- إيفليت
- جرينليت
- gevent
- بايثون بدون مكدس
استيراد asyncio و time من asyncio و Taskasync def main ( ) - > None : task1 : Task [ str ] = asyncio.create_task ( say_after ( 1 , "hello" ) ) task2 : Task [ str ] = asyncio.create_task ( say_after ( 2 , " world" ))print ( f "بدأ في { time.strftime ( ' % X ' ) } " ) ;# انتظر حتى تكتمل المهمتان (يستغرق ذلك حوالي ثانيتين) انتظر المهمة 1 انتظر المهمة 2print ( f "تم الانتهاء في { time.strftime ( ' % X ' ) } " ) ;مضرب
توفر لغة Racket استمرارية أصلية، مع تطبيق بسيط للروتينات الفرعية متوفر في كتالوج الحزم الرسمي. تم التنفيذ بواسطة S. De Gabrielle
روبي
- يدعم Ruby 1.9 الروتينات الفرعية بشكل أصلي والتي يتم تنفيذها كألياف ، وهي روتينات فرعية شبهية. [ 68 ]
- تنفيذ مارك دي شيمايكر
- يدعم Ruby 2.5 والإصدارات الأحدث الروتينات الفرعية بشكل أصلي، والتي يتم تنفيذها كألياف .
- تنفيذ توماس دبليو برانسون
مخطط
بما أن لغة Scheme توفر دعمًا كاملاً للاستمراريات، فإن تنفيذ الروتينات الفرعية أمر بسيط للغاية، ولا يتطلب سوى الحفاظ على قائمة انتظار للاستمراريات.
أحاديث قصيرة
بما أن مكدس التنفيذ في معظم بيئات Smalltalk هو عنصر أساسي، فإنه يمكن تنفيذ الروتينات الفرعية دون الحاجة إلى مكتبة إضافية أو دعم من الآلة الافتراضية.
تي سي إل
منذ الإصدار 8.6، يدعم Tcl الروتينات الفرعية في اللغة الأساسية. [ 69 ]
فالا
تدعم لغة فالا الدوال الفرعية بشكل أصلي. صُممت هذه الدوال للاستخدام مع حلقة GTK الرئيسية، ولكن يمكن استخدامها بشكل مستقل مع الحرص على عدم استدعاء دالة الاستدعاء النهائية قبل تنفيذ أمر yield واحد على الأقل.
انظر أيضاً
- Async/await
- خط الأنابيب ، وهو نوع من الروتين الفرعي المستخدم للتواصل بين البرامج [ 70 ]
- بروتوثريدز ، تطبيق خفيف الوزن للخيوط بدون استخدام مكدس، يستخدم آلية تشبه الروتين الفرعي
مراجع
- ↑ "كيف يعمل async/await في بايثون 3.5؟" . كاتب كندي طويل القامة وساخر . 11 فبراير 2016. مؤرشف من الأصل في 10 يناير 2023. تم الاطلاع عليه في 10 يناير 2023 .
- ↑ كنوت، دونالد إرفين (1997). الخوارزميات الأساسية (ملف PDF) . فن برمجة الحاسوب. المجلد 1 ( الطبعة الثالثة). أديسون-ويسلي. القسم 1.4.5: التاريخ والمراجع، ص 229. ISBN 978-0-201-89683-1تمت أرشفة الملف (PDF) من النسخة الأصلية بتاريخ 21-10-2019.
- ↑ كونواي، ميلفين إي. (يوليو 1963). "تصميم مُجمِّع مخطط انتقالي قابل للفصل" ( ملف PDF) . اتصالات ACM . 6 (7). ACM: 396-408 . doi : 10.1145/366663.366704 . ISSN 0001-0782 . S2CID 10559786. مؤرشف (PDF) من الأصل بتاريخ 2022-04-06 . تم الاسترجاع بتاريخ 2019-10-21 – عبر مكتبة ACM الرقمية.
- ↑ مارلين، كريستوفر (1980). الكوروتينات: منهجية برمجة، وتصميم لغة، وتنفيذ . سبرينغر. ISBN 3-540-10256-6.
- ↑ آنا لوسيا دي مورا؛ روبرتو إيروساليمسكي (2009). "إعادة النظر في الروتينات الفرعية". معاملات ACM في لغات البرمجة والأنظمة . 31 (2): 1-31 . CiteSeerX 10.1.1.58.4017 . doi : 10.1145/1462166.1462167 . S2CID 9918449 .
- 1 2 كنوت، دونالد إرفين (1997). الخوارزميات الأساسية . فن برمجة الحاسوب. المجلد 1 ( الطبعة الثالثة). أديسون-ويسلي. القسم 1.4.2: الروتينات الفرعية، الصفحات 193-200. ISBN 978-0-201-89683-1.
- ↑ بيرليس، آلان ج. (سبتمبر 1982). "مقتطفات من البرمجة" . إشعارات ACM SIGPLAN . 17 (9): 7-13 . doi : 10.1145/947955.1083808 . S2CID 20512767. مؤرشف من الأصل في 17 يناير 1999.
6. التناظر مفهومٌ يُقلل التعقيد (الروتينات المساعدة تتضمن روتينات فرعية)؛ ابحث عنه في كل مكان.
- ↑ أنتوني رالستون (2000). موسوعة علوم الحاسوب . مجموعة نيتشر للنشر. ISBN 978-1-56159-248-7تم الاطلاع عليه بتاريخ 11 مايو 2013 .
- ↑ انظر على سبيل المثال مرجع لغة بايثون ( مؤرشف بتاريخ ٢٤ أكتوبر ٢٠١٢ في Wayback Machine) : " https://docs.python.org/reference/expressions.html#yieldexpr ( مؤرشف بتاريخ ٢٦ أكتوبر ٢٠١٢ في Wayback Machine، الإصدار ٥.٢.١٠. تعبيرات Yield): "كل هذا يجعل دوال المولدات مشابهةً جدًا للروتينات الفرعية؛ فهي تُنفذ عدة مرات، ولها أكثر من نقطة دخول، ويمكن إيقاف تنفيذها مؤقتًا. الفرق الوحيد هو أن دالة المولد لا تستطيع التحكم في مكان استمرار التنفيذ بعد تنفيذها؛ إذ يُنقل التحكم دائمًا إلى مُستدعي المولد."
- ↑ ميرتز، ديفيد (1 يوليو 2002). "آلات الحالة القائمة على المولدات" . بايثون الساحرة . IBM developerWorks. مؤرشف من الأصل في 28 فبراير 2009. تم الاسترجاع في 2 فبراير 2011 .
- ↑ "الروتين الفرعي: روتينات فرعية آمنة من حيث النوع باستخدام أنواع جلسات خفيفة الوزن" . مؤرشف من الأصل بتاريخ 20 يناير 2013. تم الاطلاع عليه بتاريخ 18 ديسمبر 2008 .
- ↑ "الروتينات المشتركة في لغة هاسكل" . مؤرشف من الأصل بتاريخ 2020-01-09 . تم الاطلاع عليه بتاريخ 2019-01-13 .
- ↑ "وحدة الكوروتينز (coroutines.hhf)" . دليل مكتبة HLA القياسية . مؤرشف من الأصل بتاريخ 27-04-2019 . تم الاطلاع عليه بتاريخ 04-12-2013 .
- ↑ "الجديد في جافا سكريبت 1.7" . مؤرشف من الأصل بتاريخ 8 مارس 2009. تم الاطلاع عليه بتاريخ 18 يونيو 2018 .
- ↑ "دليل جوليا - التحكم في التدفق - المهام (المعروفة أيضًا باسم الروتينات الفرعية)" . مؤرشف من الأصل بتاريخ 23 يناير 2021. تم الاطلاع عليه بتاريخ 10 فبراير 2021 .
- ↑ "ما الجديد في Kotlin 1.1" . مؤرشف من الأصل بتاريخ 11 أغسطس 2019. تم الاطلاع عليه بتاريخ 27 فبراير 2017 .
- ↑ "دليل استخدام Lua 5.2" . www.lua.org . مؤرشف من الأصل بتاريخ 13 يناير 2018. تم الاطلاع عليه بتاريخ 19 يونيو 2012 .
- ↑ "شرح استخدام async/await في بايثون" . موقع Stack Abuse . ١٧ ديسمبر ٢٠١٥. مؤرشف من الأصل في ٢٩ نوفمبر ٢٠١٩. تم الاطلاع عليه في ٢١ أكتوبر ٢٠١٩ .
- ↑ "8. العبارات المركبة — وثائق بايثون 3.8.0" . docs.python.org . مؤرشف من الأصل بتاريخ 27-11-2019 . تم الاطلاع عليه بتاريخ 11-03-2016 .
- ↑ "التجميع و/أو الروتينات الفرعية" . 19-12-2012. مؤرشف من الأصل في 13-06-2020 . تم الاسترجاع في 08-06-2015 .
- ↑ دال، أو. جيه.؛ هوار، سي. إيه. آر.، محرران. (1972). "هياكل البرامج الهرمية". البرمجة الهيكلية . لندن، المملكة المتحدة: أكاديميك برس. ص 175-220 . ISBN 978-0-12-200550-3.
- ↑ مكارتني، ج. "إعادة التفكير في لغة برمجة الموسيقى الحاسوبية: سوبر كوليدر" . مجلة الموسيقى الحاسوبية، 26(4):61-68. مطبعة معهد ماساتشوستس للتكنولوجيا، 2002.
- ↑ تنفيذ الكوروتينات لـ .NET عن طريق تغليف واجهة برمجة تطبيقات الألياف غير المُدارة (مؤرشف بتاريخ 7 سبتمبر 2008 على موقع Wayback Machine ، بقلم أجاي شانكار، مجلة MSDN)
- 1 2 3 "الروتينات الفرعية في لغة C - برين واغون" . 5 مارس 2005. مؤرشف من الأصل في 23 يوليو 2019. تم الاطلاع عليه في 7 أغسطس 2018 .
- ↑ رالف س. إنجلشال (18-23 يونيو 2000). تعدد الخيوط المحمول - حيلة مكدس الإشارات لإنشاء خيوط في مساحة المستخدم (PS) . المؤتمر التقني السنوي لـ USENIX. سان دييغو، الولايات المتحدة الأمريكية. مؤرشف من الأصل في 31 أكتوبر 2019. تم الاسترجاع في 27 نوفمبر 2017 .
- 1 2 "libco" . code.byuu.org .
- ↑ "getcontext(3) - صفحة دليل لينكس" . man7.org . مؤرشف من الأصل بتاريخ 27-11-2019 . تم الاطلاع عليه بتاريخ 22-11-2017 .
- ↑ http://swtch.com/libtask/ مؤرشف بتاريخ 15 نوفمبر 2019 على موقع Wayback Machine - مكتبة libtask للروتينات الفرعية من تطوير روس كوكس لأنظمة FreeBSD وLinux وMac OS X وSunOS
- ↑ مكتبة الكوروتين المحمولة، مؤرشفة بتاريخ 14 ديسمبر 2005 على موقع Wayback Machine - مكتبة C تستخدم إمكانيات POSIX/SUSv3
- ↑ http://www.goron.de/~froese/coro/ مؤرشف بتاريخ 10 يناير 2006 على موقع Wayback Machine - مكتبة coro الخاصة بإدغار تورنيغ لأنظمة x86، لينكس، وفري بي إس دي
- ↑ https://github.com/halayli/lthread مؤرشف بتاريخ 13 يونيو 2020 على موقع Wayback Machine - lthread هي مكتبة روتينية متعددة النوى/متعددة الخيوط مكتوبة بلغة C
- ↑ "libcoroutine: تطبيق محمول للروتينات الفرعية" . مؤرشف من الأصل بتاريخ 12 نوفمبر 2019. تم الاطلاع عليه بتاريخ 6 سبتمبر 2013 .لأنظمة FreeBSD وLinux وOS X PPC وx86 وSunOS وSymbian وغيرها
- ↑ "libconcurrency - مكتبة تزامن قابلة للتوسع للغة C" .مكتبة C بسيطة لروتينات تبديل المكدس المحمولة
- ↑ "libcoro: مكتبة C تُنفّذ الروتينات الفرعية (تعدد المهام التعاوني) بطريقة قابلة للنقل" . مؤرشف من الأصل بتاريخ 2019-12-02 . تم الاطلاع عليه بتاريخ 2008-04-17 .استُخدم كأساس لوحدة Coro perl.
- ↑ "RIBS (بنية تحتية قوية لأنظمة الواجهة الخلفية) الإصدار 2: aolarchive/ribs2" . 13 أغسطس 2019. مؤرشف من الأصل في 22 أبريل 2020. تم الاطلاع عليه في 21 أكتوبر 2019 – عبر GitHub.
- ↑ "libdill" . libdill.org . مؤرشف من الأصل بتاريخ 2019-12-02 . تم الاطلاع عليه بتاريخ 2019-10-21 .
- ↑ "مكتبة C فائقة السرعة وخفيفة الوزن للروتينات الفرعية غير المتماثلة 💎 ⛅🚀⛅🌞: hnes/libaco" . ٢١ أكتوبر ٢٠١٩. مؤرشف من الأصل في ٢٩ نوفمبر ٢٠١٨. تم الاطلاع عليه في ١٦ أكتوبر ٢٠١٨ – عبر GitHub.
- 1 2 سيمون تاتام (2000). "الروتينات الفرعية في لغة C" . مؤرشف من الأصل بتاريخ 2019-11-09 . تم الاطلاع عليه بتاريخ 2003-09-19 .
- ↑ "تنفيذ روتين فرعي بدون استخدام مكدس في لغتي C و C++: jsseldenthuis/coroutine" . ١٨ مارس ٢٠١٩. مؤرشف من الأصل في ١٣ يونيو ٢٠٢٠. تم الاطلاع عليه في ١٨ مارس ٢٠١٩ - عبر GitHub.
- ↑ https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4680.pdf مؤرشف بتاريخ 30 يونيو 2024 في أرشيف الإنترنت (Wayback Machine) - المواصفات الفنية للروتينات الفرعية
- ↑ https://en.cppreference.com/w/cpp/compiler_support#cpp20 مؤرشف بتاريخ 8 أغسطس 2022 في Wayback Machine - دعم المُصرّف الحالي للروتينات الفرعية القياسية
- ↑ cppreference.com. "std::generator" . cppreference.com . cppreference.com . تم الاطلاع عليه بتاريخ 5 أبريل 2026 .
- ↑ ديتمار كول، مايكل نادولسكي (18 مايو 2025). "إضافة نوع مهمة روتينية فرعية" (ملف PDF) . open-std.org . WG21.
- ↑ cppreference.com. "std::execution::sync_wait" . cppreference.com . cppreference.com . تم الاطلاع عليه بتاريخ 15 فبراير 2026 .
- ↑ فاغنر، بيل (11 نوفمبر 2021). "المكررات" . وثائق لغة سي شارب . مايكروسوفت . مؤرشف من الأصل في 11 أبريل 2024. تم الاسترجاع في 16 فبراير 2023 – عبر مايكروسوفت ليرن.
- ↑ فاغنر، بيل (13 فبراير 2023). "تاريخ لغة سي شارب" . وثائق سي شارب . مايكروسوفت . سي شارب الإصدار 2.0. مؤرشف من الأصل في 28 أبريل 2023. تم الاطلاع عليه في 16 فبراير 2023 - عبر مايكروسوفت ليرن.
- ↑ شون كيلي؛ والتر برايت؛ أليكس رون بيترسن؛ مارتن نواك. "Class core.thread.fiber.Fiber" . dlang.org . dlang.org . تم الاطلاع عليه في 5 أبريل 2026 .
- ↑ شون كيلي؛ أليكس رون بيترسن؛ مارتن نواك. "Class std.concurrency.Generator" . dlang.org . مؤسسة لغة D. تم الاطلاع عليه في 5 أبريل 2026 .
- ↑ أندريه ألكسندرسكو؛ ديفيد سيمشا؛ جوناثان إم ديفيس. "Interface std.range.interfaces.InputRange" . dlang.org . مؤسسة لغة D. تم الاطلاع عليه في 5 أبريل 2026 .
- ↑ "Goroutines - Effective Go" . go.dev . مؤرشف من الأصل بتاريخ 27-06-2024 . تم الاطلاع عليه بتاريخ 28-11-2022 .
- ↑ "عبارات Go - مواصفات Go" . go.dev . مؤرشف من الأصل بتاريخ 27-11-2022 . تم الاطلاع عليه بتاريخ 28-11-2022 .
- ↑ "Goroutines - جولة في لغة Go" . go.dev . مؤرشف من الأصل بتاريخ 26-06-2024 . تم الاطلاع عليه بتاريخ 28-11-2022 .
- ↑ "الأسئلة الشائعة (FAQ) - لغة البرمجة Go" . go.dev . مؤرشف من الأصل بتاريخ 22-11-2021 . تم الاطلاع عليه بتاريخ 28-11-2022 .
- ↑ "الروتينات الفرعية للغة Go" . swtch.com . مؤرشف من الأصل بتاريخ 28-09-2024 . تم الاطلاع عليه بتاريخ 24-10-2024 .
- ↑ لوكاس ستادلر (2009). "استمرارية JVM" (ملف PDF) . قمة لغة JVM. مؤرشف (ملف PDF) من الأصل بتاريخ 23 أبريل 2012. تم الاطلاع عليه بتاريخ 3 أكتوبر 2011 .
- ↑ ريمي فوركس (19 نوفمبر 2009). "يا إلهي: JVM لديها روتينات فرعية/استمرارية/ألياف وما إلى ذلك" . مؤرشف من الأصل في 19 مارس 2015.
- ↑ "ECMAScript 6: الميزات الجديدة: نظرة عامة ومقارنة - بروتوكول مُكرِّر دالة المُولِّد" . es6-features.org . مؤرشف من الأصل في 18 مارس 2018. تم الاطلاع عليه في 19 مارس 2018 .
- ↑ "تاريخ إصدارات لغة لوا" . Lua.org . مؤرشف من الأصل بتاريخ 2023-05-06 . تم الاطلاع عليه بتاريخ 2023-04-24 .
- ^ دي مورا، آنا لوسيا؛ رودريجيز، نويمي؛ ييروساميشي، روبرتو. “كوروتين في لوا” (PDF) . لوا.org . أرشفة (PDF) من النسخة الأصلية في 19 مارس 2023 . تم الاسترجاع 24 أبريل 2023 .
- ^ دي مورا، آنا لوسيا؛ رودريجيز، نويمي؛ إيروسالمشي، روبرتو (2004). "كوروتين في لوا". مجلة علوم الكمبيوتر العالمية . 10 (7): 901--924.
- ↑ https://www.mono-project.com/Continuations مؤرشف بتاريخ 25-11-2010 في أرشيف الإنترنت (Wayback Machine) - Mono Continuations
- ↑ http://blogs.msdn.com/cbrumme/archive/2004/02/21/77595.aspx مؤرشف بتاريخ 21 ديسمبر 2007 على موقع Wayback Machine ، كريس بروم، مدونة cbrumme الإلكترونية. مؤرشف بتاريخ 11 ديسمبر 2007 على موقع Wayback Machine.
- ↑ kexugit (15 سبتمبر 2005). "انتهى وضع الألياف..." docs.microsoft.com . مؤرشف من الأصل بتاريخ 2021-06-08 . تم الاطلاع عليه بتاريخ 2021-06-08 .
- ↑ "مكتبة الخيوط" . مؤرشفة من الأصل بتاريخ 25 يناير 2023. تم الاطلاع عليها بتاريخ 25 يناير 2023 .
- ↑ "RFC #31" . مؤرشف من الأصل بتاريخ 2014-09-04 . تم الاطلاع عليه بتاريخ 2014-08-30 .
- ↑ "الروتينات الفرعية والمهام" . وثائق بايثون . تم الاطلاع عليه بتاريخ 31 أكتوبر 2025 .
- ↑ "ما الجديد في بايثون 3.7" . مؤرشف من الأصل بتاريخ 28 نوفمبر 2019. تم الاطلاع عليه بتاريخ 10 سبتمبر 2021 .
- ↑ "الروتينات شبه المتزامنة" . مؤرشف من الأصل في 24 أكتوبر 2007.
- ↑ "صفحة دليل الروتينات الفرعية - أوامر Tcl المدمجة" . Tcl.tk. مؤرشفة من الأصل بتاريخ 2016-10-02 . تم الاطلاع عليها بتاريخ 2016-06-27 .
- ↑ ريتشي، دينيس م. (1980). "تطور نظام المشاركة الزمنية في يونكس". تصميم اللغة ومنهجية البرمجة . سلسلة محاضرات في علوم الحاسوب. المجلد 79. الصفحات 25-35 . doi : 10.1007/3-540-09745-7_2 . ISBN 978-3-540-09745-7S2CID 571269. مؤرشف من الأصل بتاريخ 2015-04-08 . تم الاطلاع عليه بتاريخ 2011-01-26 .
للمزيد من القراءة
- آنا لوسيا دي مورا؛ روبرتو إيروساليمسكي (2004). "إعادة النظر في الروتينات الفرعية". معاملات ACM في لغات البرمجة والأنظمة . 31 (2): 1-31 . CiteSeerX 10.1.1.58.4017 . doi : 10.1145/1462166.1462167 . S2CID 9918449 .
روابط خارجية
- مقدمة شاملة لـ "الروتينات الفرعية" من تأليف سيمون تاتام ، والموجهة نحو لغة C
- صفحة الروتينات الفرعية لبرنامج Softpanorama - تحتوي على روابط شاملة للروتينات الفرعية للغة التجميع
- الحوسبة المتزامنة
- البرامج الفرعية
