المستقبل والوعود
في علوم الحاسوب ، تُستخدم مفاهيم المستقبل ، والوعود ، والتأخيرات ، والمؤجلات لمزامنة تنفيذ البرامج في بعض لغات البرمجة المتزامنة . كل منها عبارة عن كائن يعمل كبديل لنتيجة غير معروفة في البداية، عادةً لأن حساب قيمتها لم يكتمل بعد.
اقترح دانيال ب. فريدمان وديفيد وايز مصطلح "الوعد " عام 1976، [ 1 ] وأطلق عليه بيتر هيبارد اسم "النهائي" . [ 2 ] وقُدِّم مفهوم مشابه إلى حد ما، وهو "المستقبل" ، عام 1977 في ورقة بحثية لهنري بيكر وكارل هيويت . [ 3 ]
تُستخدم مصطلحات "المستقبل" و "الوعد" و "التأخير " و "المؤجل" غالبًا بشكلٍ متبادل، على الرغم من وجود بعض الاختلافات في الاستخدام بين "المستقبل" و "الوعد" . فعند التمييز بينهما، يُمثل "المستقبل" عرضًا مؤقتًا للقراءة فقط لمتغير، بينما يُمثل "الوعد" حاوية قابلة للكتابة، تُستخدم لتعيين قيمة واحدة للمستقبل. ومن الجدير بالذكر أنه يُمكن تعريف "المستقبل" دون تحديد الوعد الذي سيُعيّن قيمته، وقد تُعيّن وعود مختلفة قيمة "مستقبل" مُعين، مع العلم أنه لا يُمكن القيام بذلك إلا مرة واحدة لكل "مستقبل". وفي حالات أخرى، يتم إنشاء "المستقبل" و"الوعد" معًا وربطهما ببعضهما: "المستقبل" هو القيمة، و"الوعد" هو الدالة التي تُعيّن القيمة - أي القيمة المُعادة (المستقبل) لدالة غير متزامنة (الوعد). ويُطلق على تعيين قيمة "المستقبل" أيضًا اسم " التنفيذ " أو "الربط " .
التطبيقات
نشأت مفاهيم المستقبل والوعود في البرمجة الوظيفية والنماذج ذات الصلة (مثل البرمجة المنطقية ) لفصل القيمة (المستقبل) عن كيفية حسابها (الوعد)، مما يسمح بإجراء الحساب بمرونة أكبر، لا سيما من خلال موازاته. لاحقًا، استُخدمت هذه المفاهيم في الحوسبة الموزعة ، لتقليل زمن الاستجابة الناتج عن عمليات الاتصال ذهابًا وإيابًا. ثم ازداد استخدامها لاحقًا من خلال السماح بكتابة برامج غير متزامنة بأسلوب مباشر ، بدلًا من أسلوب تمرير الاستمرارية .
الضمني مقابل الصريح
قد يكون استخدام المتغيرات المستقبلية ضمنيًا (حيث يحصل أي استخدام للمتغير المستقبلي على قيمته تلقائيًا، كما لو كان مرجعًا عاديًا ) أو صريحًا (حيث يجب على المستخدم استدعاء دالة للحصول على القيمة، مثل دالة get`for` java.util.concurrent.Futureفي جافا ). يُطلق على الحصول على قيمة متغير مستقبلي صريح اسم "الإجبار" أو "الاستدعاء القسري" . يمكن تنفيذ المتغيرات المستقبلية الصريحة كمكتبة، بينما تُنفذ المتغيرات المستقبلية الضمنية عادةً كجزء من لغة البرمجة.
وصفت ورقة بيكر وهيويت الأصلية المستقبلات الضمنية، المدعومة بشكل طبيعي في نموذج الممثل الحسابي ولغات البرمجة الكائنية التوجه البحتة مثل سمول توك . أما ورقة فريدمان ووايز، فقد وصفت المستقبلات الصريحة فقط، ربما بسبب صعوبة تنفيذ المستقبلات الضمنية بكفاءة على الأجهزة القياسية. تكمن الصعوبة في أن الأجهزة القياسية لا تتعامل مع المستقبلات لأنواع البيانات الأولية مثل الأعداد الصحيحة. على سبيل المثال، لا تعرف تعليمة الجمع كيفية التعامل مع 0. في لغات الممثل أو الكائن البحتة، يمكن حل هذه المشكلة بإرسال رسالة تطلب من المستقبل جمع 0 مع نفسه وإعادة النتيجة. تجدر الإشارة إلى أن أسلوب تمرير الرسائل يعمل بغض النظر عن وقت انتهاء الحساب، وأنه لا حاجة إلى أي تعديلات أو فرض.3 + future factorial(100000)future factorial(100000)+[3]3factorial(100000)
خط أنابيب الوعود
يمكن أن يؤدي استخدام المستقبلات إلى تقليل زمن الاستجابة بشكل كبير في الأنظمة الموزعة . على سبيل المثال، تُمكّن المستقبلات من تنفيذ سلسلة من الوعود ، [ 4 ] [ 5 ] كما هو مُطبق في لغتي E و Joule ، والتي كانت تُسمى أيضًا سلسلة الاستدعاءات [ 6 ] في لغة Argus .
لنفترض تعبيرًا يتضمن استدعاءات إجراءات عن بُعد تقليدية ، مثل:
t3 := ( xa() ).c( yb() )
والتي يمكن توسيعها إلى
t1 := xa(); t2 := yb(); t3 := t1.c(t2);
يحتاج كل بيان إلى إرسال رسالة واستلام رد قبل أن يتمكن البيان التالي من المتابعة. لنفترض، على سبيل المثال، أن البيانات xو yو t1و t2موجودة جميعها على نفس الجهاز البعيد. في هذه الحالة، يجب أن تتم رحلتان ذهابًا وإيابًا كاملتان عبر الشبكة إلى ذلك الجهاز قبل أن يبدأ تنفيذ البيان الثالث. سيتسبب البيان الثالث بعد ذلك في رحلة ذهاب وإياب أخرى إلى نفس الجهاز البعيد.
باستخدام العقود الآجلة، يمكن كتابة التعبير أعلاه على النحو التالي
t3 := (x <- a()) <- c(y <- b())
والتي يمكن توسيعها إلى
t1 := x <- a(); t2 := y <- b(); t3 := t1 <- c(t2);
يُستخدم هنا بناء الجملة الخاص بلغة E، حيث x <- a()تعني إرسال الرسالة a()بشكل غير متزامن إلى x. تُسند قيم مستقبلية (futures) للنتائج إلى المتغيرات الثلاثة فورًا، وينتقل التنفيذ إلى العبارات اللاحقة. t3قد تتسبب المحاولات اللاحقة لتحديد قيمة في حدوث تأخير؛ ومع ذلك، يمكن لتقنية التجزئة (pipelining) تقليل عدد عمليات الإرسال والاستقبال المطلوبة. إذا كانت المتغيرات ، xو y، و t1، و t2موجودة جميعها على نفس الجهاز البعيد، كما في المثال السابق، فيمكن للتنفيذ المُجزأ (pipelining) إجراء العملية t3بعملية إرسال واستقبال واحدة بدلًا من ثلاث. ولأن الرسائل الثلاث موجهة إلى كائنات موجودة على نفس الجهاز البعيد، فلا يلزم سوى إرسال طلب واحد واستلام استجابة واحدة تحتوي على النتيجة. t1 <- c(t2)لن يُعيق الإرسال العملية حتى لو كانت المتغيرات t1و t2على أجهزة مختلفة عن بعضها البعض، أو عن xأو y.
يجب التمييز بين تقنية تجميع الرسائل باستخدام الوعود (Promises pipelining) وتمرير الرسائل غير المتزامن المتوازي. في نظام يدعم تمرير الرسائل المتوازي ولكنه لا يدعم تقنية تجميع الرسائل، يمكن إرسال الرسائل x <- a()في y <- b()المثال أعلاه بالتوازي، ولكن إرسال الرسالة t1 <- c(t2)سيتعين عليه الانتظار حتى يتم استلام كل من t1و ، حتى لو كانت الرسائل و و و موجودة على نفس الجهاز البعيد. تزداد ميزة زمن الاستجابة النسبي لتقنية تجميع الرسائل في الحالات الأكثر تعقيدًا التي تتضمن العديد من الرسائل.t2xyt1t2
كما يجب عدم الخلط بين معالجة الرسائل المتسلسلة في أنظمة الممثلين، حيث يكون من الممكن للممثل تحديد وبدء تنفيذ سلوك للرسالة التالية قبل الانتهاء من معالجة الرسالة الحالية.
عرض للقراءة فقط
في بعض لغات البرمجة مثل Oz و E و AmbientTalk ، من الممكن الحصول على عرض للقراءة فقط للمستقبل، مما يسمح بقراءة قيمته عند حله، ولكنه لا يسمح بحله:
- في أوز،
!!يتم استخدام المعامل للحصول على عرض للقراءة فقط. - في لغة E ولغة AmbientTalk، يتم تمثيل المستقبل بزوج من القيم يسمى زوج الوعد/المُحلِّل . يمثل الوعد العرض للقراءة فقط، والمُحلِّل ضروري لتعيين قيمة المستقبل.
- في لغة C++ (منذ C++11 )،
std::future<T>يوفر المتغير `a` عرضًا للقراءة فقط. تُحدد القيمة مباشرةً باستخدام `a`std::promise<T>، أو تُحدد كنتيجة استدعاء دالة باستخدام `a`std::packaged_task<R(Ts...)>أوstd::async()الدالة `a`. تُقدم C++26std::execution::task<T, Env>متغيرًا مناسبًا `a` . - في واجهة برمجة التطبيقات المؤجلة (Deferred API) الخاصة بمجموعة أدوات Dojo اعتبارًا من الإصدار 1.5، يمثل كائن الوعد الخاص بالمستهلك فقط عرضًا للقراءة فقط. [ 7 ]
- في لغة Alice ML ، توفر المستقبلات عرضًا للقراءة فقط ، بينما يحتوي الوعد على كل من المستقبل والقدرة على حل المستقبل [ 8 ] [ 9 ]
- في بيئة .NET
System.Threading.Tasks.Task<T>، يمثل هذا عنصر عرض للقراءة فقط. ويمكن تحديد القيمة عبرSystem.Threading.Tasks.TaskCompletionSource<T>.
يتوافق دعم العرض للقراءة فقط مع مبدأ أقل الامتيازات ، إذ يُمكّن من حصر إمكانية تعيين القيمة على الجهات التي تحتاج إلى تعيينها. في نظام يدعم أيضًا تقنية التجزئة، يتلقى مُرسِل الرسالة غير المتزامنة (مع النتيجة) وعدًا للقراءة فقط للنتيجة، بينما يتلقى مُستقبِل الرسالة المُحلِّل.
العقود الآجلة الخاصة بكل موضوع
تُعرّف بعض لغات البرمجة، مثل Alice ML ، كائنات مستقبلية مرتبطة بخيط معالجة مُحدد يقوم بحساب قيمتها. [ 9 ] يمكن أن يبدأ هذا الحساب إما فور إنشاء الكائن المستقبلي، أو عند الحاجة إلى قيمته لأول مرة. يُشبه الكائن المستقبلي المُؤجل عملية thunk ، من حيث كونه حسابًا مؤجلًا.
يدعم Alice ML أيضًا الكائنات المستقبلية التي يمكن لأي خيط برمجي حلّها، ويُطلق عليها اسم "الوعود" . [ 8 ] يختلف استخدام الوعود هنا عن استخدامها في E كما هو موضح أعلاه . في Alice، لا تُعدّ الوعود عرضًا للقراءة فقط، ولا يدعم Alice تجميع الوعود. بدلًا من ذلك، يحدث التجميع تلقائيًا للكائنات المستقبلية، بما في ذلك تلك المرتبطة بالوعود.
دلالات الحظر مقابل دلالات عدم الحظر
إذا تم الوصول إلى قيمة مستقبلية بشكل غير متزامن، على سبيل المثال عن طريق إرسال رسالة إليها، أو عن طريق انتظارها صراحةً باستخدام بنية مثل تلك الموجودة whenفي اللغة الإنجليزية، فلا توجد صعوبة في التأخير حتى يتم حلّ المستقبلية قبل استلام الرسالة أو اكتمال الانتظار. هذه هي الحالة الوحيدة التي يجب مراعاتها في الأنظمة غير المتزامنة تمامًا مثل لغات الممثلين البحتة.
مع ذلك، قد يكون من الممكن في بعض الأنظمة محاولة الوصول الفوري أو المتزامن إلى قيمة مستقبلية. عندها يصبح من الضروري اتخاذ قرار تصميمي.
- قد يؤدي الوصول إلى حظر الخيط أو العملية الحالية حتى يتم حل المشكلة المستقبلية (ربما مع مهلة زمنية). هذا هو مفهوم متغيرات تدفق البيانات في لغة Oz .
- قد يؤدي الوصول المتزامن المُحاول دائمًا إلى الإشارة إلى وجود خطأ، على سبيل المثال، طرح استثناء . هذه هي دلالات الوعود البعيدة في اللغة الإنجليزية. [ 10 ]
- من المحتمل أن ينجح الوصول إذا كان المستقبل محسومًا بالفعل، ولكنه سيشير إلى وجود خطأ إذا لم يكن كذلك. لكن هذا سيؤدي إلى إدخال عنصر عدم الحتمية واحتمالية حدوث حالات تضارب ، ويبدو أنه خيار تصميم غير شائع.
كمثال على الاحتمال الأول، في لغة C++11 ، يمكن للخيط الذي يحتاج إلى قيمة كائن مستقبلي أن ينتظر حتى تصبح القيمة متاحة عن طريق استدعاء الدوال الأعضاء wait()`get` أو ` get()get`. كما يمكن تحديد مهلة زمنية للانتظار باستخدام الدوال الأعضاء wait_for()`get` أو ` get` (في C++ ) لتجنب الانتظار غير المحدد. إذا نشأ الكائن المستقبلي من استدعاء الدالة `get`، فقد يؤدي الانتظار المُعطِّل (بدون مهلة زمنية) إلى استدعاء متزامن للدالة لحساب النتيجة على الخيط المنتظر.wait_until()std::condition_variablestd::async()
المفاهيم ذات الصلة
تُعدّ الأحداث المستقبلية حالة خاصة من عناصر التزامن الأساسية " الأحداث "، والتي لا يمكن إكمالها إلا مرة واحدة. وبشكل عام، يمكن إعادة ضبط الأحداث إلى حالتها الأولية الفارغة، وبالتالي إكمالها عدة مرات حسب الرغبة. [ 11 ]
المتغير I (كما في لغة Id ) هو متغير مستقبلي ذو دلالات حظر كما هو موضح أعلاه. بنية I هي بنية بيانات تحتوي على متغيرات I. يُطلق على بنية التزامن ذات الصلة، والتي يمكن تعيينها عدة مرات بقيم مختلفة، اسم المتغير M. تدعم المتغيرات M عمليات ذرية لأخذ القيمة الحالية أو إضافتها ، حيث يؤدي أخذ القيمة إلى إعادة المتغير M إلى حالته الفارغة الأولية . [ 12 ]
يُشبه متغير المنطق المتزامن متغير المستقبل، ولكنه يُحدَّث عبر التوحيد ، تمامًا كما هو الحال مع متغيرات المنطق في البرمجة المنطقية . وبالتالي، يمكن ربطه أكثر من مرة بقيم قابلة للتوحيد، ولكن لا يمكن إعادته إلى حالة فارغة أو غير مُحَلَّلة. تعمل متغيرات تدفق البيانات في Oz كمتغيرات منطق متزامنة، ولها أيضًا دلالات حظر كما ذُكر سابقًا.
متغير القيد المتزامن هو تعميم لمتغيرات المنطق المتزامن لدعم برمجة منطق القيود : يمكن تضييق نطاق القيد عدة مرات، مما يشير إلى مجموعات أصغر من القيم الممكنة. عادةً ما توجد طريقة لتحديد دالة برمجية (thunk) يتم تشغيلها كلما تم تضييق نطاق القيد بشكل أكبر؛ وهذا ضروري لدعم انتشار القيود .
العلاقات بين قدرة التعبير عن أشكال المستقبل المختلفة
يمكن تنفيذ عمليات المستقبل الخاصة بالخيوط بشكل مباشر في عمليات المستقبل غير الخاصة بالخيوط، وذلك بإنشاء خيط لحساب القيمة بالتزامن مع إنشاء عملية المستقبل. في هذه الحالة، يُفضّل إرجاع عرض للقراءة فقط إلى العميل، بحيث يكون الخيط الذي تم إنشاؤه حديثًا هو الوحيد القادر على حلّ عملية المستقبل هذه.
يتطلب تنفيذ عمليات مستقبلية ضمنية كسولة خاصة بالخيوط (كما هو الحال في Alice ML، على سبيل المثال) باستخدام عمليات مستقبلية غير خاصة بالخيوط، آلية لتحديد وقت الحاجة إلى قيمة العملية المستقبلية (على سبيل المثال، البنية WaitNeededالمذكورة في Oz [ 13 ] ). إذا كانت جميع القيم عبارة عن كائنات، فإن القدرة على تنفيذ كائنات توجيه شفافة كافية، لأن الرسالة الأولى المرسلة إلى المُوجِّه تُشير إلى الحاجة إلى قيمة العملية المستقبلية.
يمكن تنفيذ العمليات المستقبلية غير المرتبطة بخيوط محددة ضمن العمليات المستقبلية المرتبطة بخيوط محددة، بافتراض أن النظام يدعم تمرير الرسائل، وذلك عن طريق قيام الخيط المُنفِّذ بإرسال رسالة إلى خيط العملية المستقبلية نفسه. مع ذلك، قد يُنظر إلى هذا على أنه تعقيد غير ضروري. في لغات البرمجة القائمة على الخيوط، يبدو أن الأسلوب الأمثل هو توفير مزيج من العمليات المستقبلية غير المرتبطة بخيوط محددة، وعروض للقراءة فقط، بالإضافة إلى بنية WaitNeeded أو دعم التوجيه الشفاف.
استراتيجية التقييم
تُعدّ استراتيجية تقييم القيم المستقبلية، والتي يُمكن تسميتها " الاستدعاء حسب القيمة المستقبلية" ، غير حتمية: إذ يتم تقييم قيمة القيمة المستقبلية في وقت ما بين إنشائها واستخدامها، ولكن هذا الوقت الدقيق غير مُحدد مسبقًا، وقد يتغير من تشغيل لآخر. يُمكن أن يبدأ الحساب فور إنشاء القيمة المستقبلية ( التقييم الفوري ) أو فقط عند الحاجة الفعلية للقيمة ( التقييم المؤجل )، وقد يتوقف في منتصف العملية، أو يُنفذ في تشغيل واحد. بمجرد تعيين قيمة القيمة المستقبلية، لا يُعاد حسابها عند الوصول إليها لاحقًا؛ وهذا يُشبه التخزين المؤقت المُستخدم في "الاستدعاء حسب الحاجة" .
أالمستقبل الكسول هو مستقبل يتميز بآلية تقييم كسولة حتمية: يبدأ حساب قيمة المستقبل عند الحاجة إليها لأول مرة، كما في الاستدعاء عند الحاجة. تُستخدم المستقبلات الكسولة في اللغات التي لا تعتمد استراتيجية التقييم الكسولة افتراضيًا. على سبيل المثال، في لغةC++11،يمكن إنشاء هذه المستقبلات الكسولة بتمريرstd::launch::deferredسياسة التشغيل إلى الدالةstd::async()، بالإضافة إلى الدالة اللازمة لحساب القيمة.
دلالات المستقبل في نموذج الفاعل
في نموذج الممثل، يُعرَّف التعبير بالشكل التالي future <Expression>من خلال كيفية استجابته لرسالة Evalتتضمن البيئة E والعميل C : يستجيب التعبير المستقبلي للرسالة Evalبإرسال ممثل F مُنشأ حديثًا (وهو وكيل استجابة التقييم ) إلى العميل C كقيمة مُعادة، بالتزامن مع إرسال رسالة تتضمن البيئة E والعميل C. السلوك الافتراضي لـ F هو كما يلي:<Expression><Expression>Eval
- عندما يتلقى F طلبًا R ، فإنه يتحقق مما إذا كان قد تلقى بالفعل استجابة (يمكن أن تكون إما قيمة إرجاع أو استثناء تم طرحه) من التقييم،
<Expression>ويتابع على النحو التالي:- إذا كان لديه بالفعل استجابة V ، فـ
- إذا كانت V قيمة إرجاع، فسيتم إرسال الطلب R إليها .
- إذا كان V استثناءً ، فسيتم طرحه على عميل الطلب R.
- إذا لم يكن لديه رد بالفعل، فسيتم تخزين R في قائمة الطلبات داخل F.
- إذا كان لديه بالفعل استجابة V ، فـ
- عندما تتلقى F الاستجابة V من عملية التقييم
<Expression>، يتم تخزين V في F و- إذا كانت V هي قيمة الإرجاع، فسيتم إرسال جميع الطلبات الموجودة في قائمة الانتظار إلى V.
- إذا كان V استثناءً، فسيتم طرحه على عميل كل طلب من الطلبات الموجودة في قائمة الانتظار.
مع ذلك، يمكن لبعض المتغيرات المستقبلية التعامل مع الطلبات بطرق خاصة لتوفير توازي أكبر. على سبيل المثال، 1 + future factorial(n)يمكن للتعبير إنشاء متغير مستقبلي جديد يتصرف مثل الرقم 1+factorial(n). لكن هذه الحيلة لا تنجح دائمًا. على سبيل المثال، التعبير الشرطي التالي:
if m>future factorial(n) then print("bigger") else print("smaller")
يتم تعليق العملية حتى factorial(n)يتم الرد على الطلب الذي يسأل عما إذا mكان أكبر من نفسه.
تاريخ
طُبقت مفاهيم المستقبل والوعد لأول مرة في لغات برمجة مثل MultiLisp و Act 1. وكان استخدام المتغيرات المنطقية للتواصل في لغات البرمجة المنطقية المتزامنة مشابهًا جدًا للمستقبل. بدأ هذا في لغة Prolog مع Freeze و IC Prolog ، وأصبح عنصرًا أساسيًا في التزامن مع لغات مثل Relational Language وConcurrent Prolog وGuarded Horn clauses (GHC) وParlog وStrand وVulcan وJanus وOz-Mozart وFlow Java وAlice ML. ويُشبه متغير I - var ذو التعيين الواحد ، المُستخدم في لغات برمجة تدفق البيانات ، والذي نشأ في لغة Id ومُضمن في Concurrent ML الخاصة بـ Reppy ، متغير المنطق المتزامن إلى حد كبير.
تم اختراع تقنية خط أنابيب الوعود (باستخدام المستقبلات للتغلب على زمن الاستجابة) بواسطة باربرا ليسكوف وليوبا شريرا في عام 1988، [ 6 ] وبشكل مستقل بواسطة مارك إس. ميلر ودين تريبل وروب جيلينجهاوس في سياق مشروع زانادو حوالي عام 1989. [ 14 ]
صاغ ليسكوف وشريرا مصطلح الوعد ، على الرغم من أنهم أشاروا إلى آلية خط الأنابيب باسم call-stream ، وهو مصطلح نادر الاستخدام الآن.
كان لكل من التصميم الموصوف في ورقة ليسكوف وشريرة، وتطبيق سلسلة الوعود في زانادو، قيدٌ يتمثل في أن قيم الوعود لم تكن من الدرجة الأولى : فلا يمكن أن يكون وسيط الاستدعاء أو الإرسال، أو القيمة المُعادة منه، وعدًا بشكل مباشر (لذا فإن مثال سلسلة الوعود المذكور سابقًا، والذي يستخدم وعدًا لنتيجة إرسال واحد كوسيط لآخر، لم يكن ليُمكن التعبير عنه بشكل مباشر في تصميم سلسلة الاستدعاءات أو في تطبيق زانادو). ويبدو أن الوعود وسلاسل الاستدعاءات لم تُطبَّق أبدًا في أي إصدار عام من أرجوس، [ 15 ] لغة البرمجة المستخدمة في ورقة ليسكوف وشريرة. توقف تطوير أرجوس حوالي عام 1988. [ 16 ] لم يُصبح تطبيق زانادو لسلسلة الوعود متاحًا للجمهور إلا مع إصدار الشفرة المصدرية لأوداناكس جولد [ 17 ] في عام 1999، ولم يُشرح في أي وثيقة منشورة. [ 18 ] تدعم التطبيقات اللاحقة في جول وإي الوعود والمُحلِّلات من الدرجة الأولى بشكل كامل.
دعمت العديد من لغات البرمجة المبكرة، بما في ذلك سلسلة Act، [ 19 ] [ 20 ] كلاً من تمرير الرسائل المتوازي ومعالجة الرسائل المتسلسلة، لكنها لم تدعم معالجة الوعود المتسلسلة. (على الرغم من أنه من الممكن تقنيًا تنفيذ الميزة الأخيرة في اللغتين الأوليين، إلا أنه لا يوجد دليل على أن لغات Act قد فعلت ذلك).
بعد عام 2000، حدث انتعاش كبير في الاهتمام بالعقود المستقبلية والوعود، وذلك بسبب استخدامها في استجابة واجهات المستخدم، وفي تطوير الويب ، بسبب نموذج الطلب والاستجابة لتمرير الرسائل. تدعم العديد من لغات البرمجة الشائعة الآن صيغ المستقبل والوعود، وقد شاع استخدامها بشكل ملحوظ FutureTaskفي Java 5 (التي أُعلن عنها في عام 2004) [ 21 ] وبنيات async/await في .NET 4.5 (التي أُعلن عنها في عام 2010، وصدرت في عام 2012) [ 22 ] [ 23 ]، والتي استُلهمت إلى حد كبير من سير العمل غير المتزامن في F#، [ 24 ] والذي يعود تاريخه إلى عام 2007. [ 25 ] وقد تم اعتماد هذا لاحقًا من قبل لغات أخرى، ولا سيما Dart (2014)، [ 26 ] وPython (2015)، [ 27 ] وHack (HHVM)، ومسودات ECMAScript 7 (JavaScript)، وScala، وC++ (2011).
قائمة التطبيقات
تدعم بعض لغات البرمجة المتغيرات المستقبلية، والوعود، ومتغيرات المنطق المتزامن، ومتغيرات تدفق البيانات، أو المتغيرات المستقلة، إما من خلال دعم اللغة المباشر أو في المكتبة القياسية.
قائمة بالمفاهيم المتعلقة بالمستقبلات والوعود حسب لغة البرمجة
- ABCL/f [ 28 ]
- أليس إم إل
- AmbientTalk (بما في ذلك المُحلِّلات من الدرجة الأولى والوعود للقراءة فقط)
- لغة C++ ، بدءًا من C++11 عبر
std::futureوstd::promise- لغة C++ التركيبية
- كريستال
- Dart (مع الفئات
Future/ [ 29 ] والكلمات المفتاحية و [ 26 ] )Completerawaitasync - إلم عبر وحدة المهام [ 30 ]
- هاسكل عبر المكتبات
Control.Concurrent.Async(I-vars) وControl.Concurrent.MVar(M-vars) - المعرف (للمتغيرات الفردية والمتغيرات المتعددة فقط)
- Io [ 31 ]
- جافا عبر
java.util.concurrent.Futureأوjava.util.concurrent.CompletableFuture - JavaScript اعتبارًا من ECMAScript 2015، [ 32 ] وعبر الكلمات الرئيسية
asyncومنذawaitECMAScript 2017 [ 33 ] - لوسيد (تدفق البيانات فقط)
- بعض التلعثم
- .NET عبر
System.Threading.Tasks.Task - Kotlin ، على الرغم من
kotlin.native.concurrent.Futureأنها تستخدم عادة فقط عند كتابة Kotlin التي تهدف إلى التشغيل بشكل أصلي [ 35 ] - نيم
- الأكسجين
- أوز الإصدار 3 [ 36 ]
- تم إضافة concurrent.futures في بايثون ، [ 37 ] منذ الإصدار 3.2، [ 38 ] كما اقترح PEP 3148، [ 39 ] وتمت إضافتها في بايثون 3.5
asyncوawait[ 40 ] - R (الوعود للتقييم الكسول، لا يزال أحادي الخيوط)
- المضرب [ 41 ]
- راكو [ 42 ]
- Rust (future as
std::future::Future, promise achieve via.await) [ 43 ] - Scala عبر حزمة scala.concurrent
- مخطط
- حديث قصير غير واضح
- ستراند
- Swift (فقط عبر مكتبات الطرف الثالث)
- Visual Basic 11 (عبر الكلمات الرئيسية Async و Await ) [ 23 ]
تشمل اللغات التي تدعم أيضًا تقنية تجميع الوعود ما يلي:
قائمة بتطبيقات المكتبات لـ Futures
- للغة Common Lisp :
- بالنسبة للغة C++:
- بالنسبة للغة C# ولغات .NET الأخرى : مكتبة Parallel Extensions
- لـ Groovy : GPars [ 56 ]
- بالنسبة للغة جافا سكريبت :
- يوفر كل من Cujo.js [ 57 ] و when.js [ 58 ] وعودًا تتوافق مع مواصفات Promises/A+ [ 59 ] 1.1
- توفر مجموعة أدوات الدوجو وعودًا [ 60 ] وتأجيلات بأسلوب تويستد
- MochiKit [ 61 ] مستوحى من Deferreds لفرقة Twisted
- يعتمد كائن Deferred الخاص بـ jQuery على تصميم CommonJS Promises/A .
- AngularJS [ 62 ]
- node -promise [ 63 ]
- يتوافق Q، من تأليف كريس كوال، مع Promises/A+ 1.1 [ 64 ]
- يتوافق RSVP.js مع Promises/A+ 1.1 [ 65 ]
- يتوافق صنف الوعد [ 66 ] الخاص بـ YUI [ 67 ] مع مواصفات Promises/A+ 1.0.
- بلوبيرد، بقلم بيتكا أنتونوف [ 68 ]
- تتوافق حزمة الوعود الخاصة بمكتبة الإغلاق مع مواصفات Promises/A+.
- راجع قائمة Promise/A+ لمزيد من التطبيقات المستندة إلى تصميم Promise/A+.
- بالنسبة للغة جافا :
- للغة Lua :
- بالنسبة للغة Objective-C : MAFuture، [ 71 ] [ 72 ] RXPromise، [ 73 ] ObjC-CollapsingFutures، [ 74 ] PromiseKit، [ 75 ] objc-promise، [ 76 ] OAPromise، [ 77 ]
- بالنسبة لـ OCaml : وحدة Lazy تنفذ المستقبلات الصريحة الكسولة [ 78 ]
- بالنسبة لـ Perl : Future، [ 79 ] Promises، [ 80 ] Reflex، [ 81 ] Promise::ES6، [ 82 ] و Promise::XS [ 83 ]
- بالنسبة لـ PHP : React/Promise [ 84 ]
- بالنسبة للغة بايثون :
- بالنسبة لـ R :
- للغة روبي :
- بالنسبة لـ Rust :
- futures-rs [ 95 ]
- بالنسبة للغة سكالا :
- للغة Swift :
- إطار عمل غير متزامن، ينفذ نمط C#
async/ غير الحظرawait[ 97 ] - FutureKit، [ 98 ] ينفذ إصدارًا لـ Apple GCD [ 99 ]
- FutureLib، مكتبة Swift 2 خالصة تنفذ المستقبلات والوعود على نمط Scala مع إلغاء على نمط TPL [ 100 ]
- Deferred، مكتبة Swift خالصة مستوحاة من Deferred في OCaml [ 101 ]
- برايت فيوتشرز [ 102 ]
- SwiftCoroutine [ 103 ]
- إطار عمل غير متزامن، ينفذ نمط C#
- بالنسبة لـ Tcl : tcl-promise [ 104 ]
الروتينات الفرعية
يمكن تنفيذ المستقبلات في الروتينات الفرعية [ 27 ] أو المولدات ، [ 105 ] مما يؤدي إلى نفس استراتيجية التقييم (على سبيل المثال، تعدد المهام التعاوني أو التقييم الكسول).
القنوات
يمكن تنفيذ المتغيرات المستقبلية بسهولة في القنوات : فالمتغير المستقبلي عبارة عن قناة أحادية العنصر، والوعد عبارة عن عملية تُرسل إلى القناة، مُحققةً بذلك المتغير المستقبلي. [ 106 ] [ 107 ] وهذا يسمح بتنفيذ المتغيرات المستقبلية في لغات البرمجة المتزامنة التي تدعم القنوات، مثل CSP و Go . وتكون المتغيرات المستقبلية الناتجة صريحة، إذ يجب الوصول إليها عن طريق القراءة من القناة، وليس فقط عن طريق التقييم.
انظر أيضاً
- Async/await
- الألياف (علوم الحاسوب)
- فوتكس
- هرم الهلاك (برمجة) ، نمط تصميمي سيئ يتم تجنبه عن طريق الوعود
مراجع
- ↑ فريدمان، دانيال؛ ديفيد وايز (1976). أثر البرمجة التطبيقية على المعالجة المتعددة . المؤتمر الدولي للمعالجة المتوازية. الصفحات 263-272 . نسخة أولية من: فريدمان، دانيال؛ وايز، ديفيد (أبريل 1978). "جوانب البرمجة التطبيقية للمعالجة المتوازية". معاملات IEEE في الحوسبة . C-27 (4): 289-296 . CiteSeerX 10.1.1.295.9692 . doi : 10.1109/tc.1978.1675100 . S2CID 16333366 .
- ↑ هيبارد، بيتر (1976). مرافق المعالجة المتوازية . اتجاهات جديدة في لغات الخوارزميات، (تحرير) ستيفن أ. شومان، IRIA، 1976.
- ↑ هنري بيكر؛ كارل هيويت (أغسطس 1977). التجميع التدريجي للنفايات في العمليات . وقائع ندوة لغات برمجة الذكاء الاصطناعي. ACM SIGPLAN Notices 12، 8، ص 55-59. مؤرشف من الأصل في 4 يوليو 2008. تم الاطلاع عليه في 13 فبراير 2015 .
- ↑ مشروع Promise Pipelining على موقع erights.org
- ↑ تقنية Promise Pipelining على ويكي C2
- 1 2 باربرا ليسكوف؛ ليوبا شريرا (1988). "الوعود: الدعم اللغوي لاستدعاءات الإجراءات غير المتزامنة الفعالة في الأنظمة الموزعة". وقائع مؤتمر SIGPLAN '88 حول تصميم لغات البرمجة وتنفيذها؛ أتلانتا، جورجيا، الولايات المتحدة . ACM. الصفحات 260-267 . doi : 10.1145/53990.54016 . ISBN 0-89791-269-1.نُشر أيضًا في ACM SIGPLAN Notices 23 (7).
- ↑ وعود قوية مع تأجيل افتتاح الدوجو ، موقع بن، 3 مايو 2010
- 1 2 "الوعد" ، دليل أليس ، ألمانيا: Uni-SB، مؤرشف من الأصل في 8 أكتوبر 2008 ، تم استرجاعه في 21 مارس 2007
- 1 2 "المستقبل" ، دليل أليس ، ألمانيا: Uni-SB، مؤرشف من الأصل في 6 أكتوبر 2008 ، تم استرجاعه في 21 مارس 2007
- ↑ وعد ، حقوق إلكترونية
- ↑ في 500 سطر أو أقل، يقول "برنامج زحف الويب باستخدام الروتينات الفرعية غير المتزامنة" بقلم أ. جيسي جيريو ديفيس وغيدو فان روسوم: "يستخدم التنفيذ asyncio.Event بدلاً من Future الموضح هنا. والفرق هو أنه يمكن إعادة ضبط Event، بينما لا يمكن لـ Future الانتقال من حالة محلولة إلى حالة معلقة."
- ↑ التحكم في المتغيرات المتعددة المتزامنة ، هاسكل، مؤرشف من الأصل في 18 أبريل 2009
- ↑ WaitNeeded ، موزارت أوز، مؤرشف من الأصل في 17 مايو 2013 ، تم استرجاعه في 21 مارس 2007
- ↑ وعد ، بحر بلا شمس، مؤرشف من الأصل في 23 أكتوبر 2007
- ↑ أرجوس ، معهد ماساتشوستس للتكنولوجيا
- ↑ ليسكوف، باربرا (26 يناير 2021)، الحوسبة الموزعة وبرنامج أرجوس ، تاريخ شفوي، IEEE GHN
- ↑ غولد ، أوداناكس، مؤرشف من الأصل في 11 أكتوبر 2008
- ↑ خط الأنابيب ، الحقوق الإلكترونية
- ↑ هنري ليبرمان (يونيو 1981). "معاينة للفصل الأول". مذكرة معهد ماساتشوستس للتكنولوجيا للذكاء الاصطناعي 625 .
- ↑ هنري ليبرمان (يونيو 1981). "التفكير في أشياء كثيرة في وقت واحد دون الشعور بالارتباك: التوازي في الفصل الأول". مذكرة معهد ماساتشوستس للتكنولوجيا للذكاء الاصطناعي 626 .
- ↑ غوتز، برايان (23 نوفمبر 2004). "التزامن في JDK 5.0" . IBM .
- 1 2 "البرمجة غير المتزامنة في الإصدار 4.5: تستحق الانتظار - مدونة .NET - الصفحة الرئيسية للموقع - مدونات MSDN" . Blogs.msdn.com . تم الاطلاع عليه بتاريخ 13 مايو 2014 .
- 1 2 3 "البرمجة غير المتزامنة باستخدام Async وAwait (C# وVisual Basic)" . Msdn.microsoft.com . تم الاطلاع عليه بتاريخ 13 مايو 2014 .
- ↑ توماس بيتريتشيك (29 أكتوبر 2010). "لغة C# و F# غير المتزامنة (الجزء الأول): مقدمة متزامنة" .
- ^ دون سايم. توماس بيتريسيك؛ ديمتري لوموف (21 أكتوبر 2010). "نموذج البرمجة غير المتزامنة F#، PADL 2011" .
- 1 2 براخا، جلعاد (أكتوبر 2014). "دعم عدم التزامن في لغة دارت: المرحلة 1" .
- 1 2 "PEP 0492 – Coroutines with async and await syntax" .
- ↑ تاورا، كينجيرو؛ ماتسوكا، ساتوشي؛ يونيزاوا، أكينوري (1994). "ABCL/f: لغة برمجة كائنية التوجه متزامنة متعددة الأشكال قائمة على المستقبل - تصميمها وتنفيذها". وقائع ورشة عمل DIMACS حول مواصفات الخوارزميات المتوازية . سلسلة DIMACS في الرياضيات المتقطعة وعلوم الحاسوب النظرية. المجلد 18. الجمعية الأمريكية للرياضيات. الصفحات 275-292 . CiteSeerX 10.1.1.23.1161 .
- ^ "Dart SDK Dart async Completer" .
- ↑ "مهمة" .
- ↑ ستيف ديكورت (2005). "Io، لغة البرمجة" .
- ↑ "استخدام الوعود" . شبكة مطوري موزيلا . تم الاطلاع عليه بتاريخ 23 فبراير 2021 .
- ↑ "تسهيل البرمجة غير المتزامنة باستخدام async و await" . شبكة مطوري موزيلا . تم الاطلاع عليه بتاريخ 23 فبراير 2021 .
- ↑ هيكي، ريتش (2009). "changes.txt في الإصدار 1.1.x من clojure الخاص بـ richhickey" . GitHub .
- ↑ "المستقبل - لغة برمجة كوتلين" .
- ↑ حريدي، سيف؛ فرانزن، نيلز. "دليل أوز" . مكتبة موزارت العالمية للمستخدمين. مؤرشف من الأصل في 14 مايو 2011. تم الاطلاع عليه في 12 أبريل 2011 .
- ↑ "concurrent.futures — تشغيل المهام المتوازية" . وثائق بايثون . تم الاطلاع عليه بتاريخ 25 مارس 2026 .
- ↑ إصدار بايثون 3.2
- ↑ "PEP 3148 – المستقبلات - تنفيذ العمليات الحسابية بشكل غير متزامن | peps.python.org" . مقترحات تحسين بايثون (PEPs) . تم الاطلاع عليه بتاريخ 25 مارس 2026 .
- ↑ إصدار بايثون 3.5
- ↑ "التوازي مع المستقبل" . PLT . تم الاطلاع عليه في 2 مارس 2012 .
- ↑ "class Promise" . raku.org . تم الاطلاع عليه بتاريخ 19 أغسطس 2022 .
- ↑ "Future in std::future - Rust" . doc.rust-lang.org . تم الاطلاع عليه بتاريخ 16 ديسمبر 2023 .
- ↑ طائر الشحرور ذو اللسان الشائع
- ↑ لغة ليسب الشائعة: مستقبلٌ واعد 2
- ↑ ليسب بالتوازي – مكتبة برمجة متوازية للغة Common Lisp
- ↑ برنامج الاتصال بشبكة لغة ليسب الشائعة
- ↑ "الفصل 30. الخيط 4.0.0" . تم الاطلاع عليه بتاريخ 26 يونيو 2013 .
- ↑ "مكتبة Dlib C++ #thread_pool" . تم الاطلاع عليه بتاريخ 26 يونيو 2013 .
- ↑ "GitHub – facebook/folly: مكتبة C++ مفتوحة المصدر تم تطويرها واستخدامها في فيسبوك" . GitHub . 8 يناير 2019.
- ↑ "HPX" . 10 فبراير 2019.
- ↑ "شرائح عرض سلاسل POCO" (ملف PDF) .
- ↑ "QtCore 5.0: فئة QFuture" . مشروع Qt. مؤرشف من الأصل في 1 يونيو 2013. تم الاطلاع عليه في 26 يونيو 2013 .
- ^ "سيستار" . مشروع سي ستار . تم الاسترجاع في 22 أغسطس 2016 .
- ↑ "stlab هو العمل المستمر لما كان يُعرف سابقًا باسم مختبر تقنيات البرمجيات في Adobe. يتم استضافة مكتبات Adobe المصدرية (ASL) ومكتبات المنصات ومكتبات stlab الجديدة على GitHub" . 31 يناير 2021.
- ↑ تم أرشفة Groovy GPars في 12 يناير 2013 على موقع Wayback Machine
- ↑ Cujo.js
- ↑ جافا سكريبت when.js
- ↑ وعود/مواصفات A+
- ↑ وعود
- ↑ جافا سكريبت MochKit.Async
- ↑ جافا سكريبت أنجولار جي إس
- ↑ وعد العقدة في جافا سكريبت
- ↑ "سؤال حول جافا سكريبت" . مؤرشف من الأصل في 31 ديسمبر 2018. تم الاطلاع عليه في 8 أبريل 2013 .
- ↑ جافا سكريبت RSVP.js
- ↑ مكتبة فئات جافا سكريبت YUI
- ↑ فئة وعد جافا سكريبت YUI
- ↑ جافا سكريبت بلو بيرد
- ↑ جافا JDeferred
- ↑ جافا بار سيك
- ↑ Objective-C MAFuture GitHub
- ↑ Objective-C MAFuture mikeash.com
- ↑ Objective-C RXPromise
- ↑ ObjC-CollapsingFutures
- ↑ مجموعة أدوات PromiseKit للغة Objective-C
- ↑ Objective-C objc-promise
- ↑ Objective-C OAPromise
- ↑ OCaml كسول
- ↑ مستقبل بيرل
- ↑ وعود بيرل
- ↑ انعكاس بيرل
- ↑ Perl Promise::ES6
- ↑ "Promise::XS – وعود سريعة في لغة بيرل – metacpan.org" . metacpan.org . تم الاطلاع عليه بتاريخ 14 فبراير 2021 .
- ↑ PHP React/Promise
- ↑ تطبيق بايثون المدمج
- ↑ pythonfutures
- ↑ "مرجع مؤجل" . وثائق تويستد . مختبرات تويستد ماتريكس. مؤرشف من الأصل في 25 يونيو 2026.
- ↑ حزمة R المستقبلية
- ↑ المستقبل
- ↑ روبي المتزامن
- ↑ جوهرة روبي بروميس
- ↑ روبي ليبوف
- ↑ "جوهرة من السيلولويد الياقوتي" . مؤرشف من الأصل في 8 مايو 2013. تم الاطلاع عليه في 19 فبراير 2022 .
- ↑ موارد روبي المستقبلية
- ↑ حزمة futures-rs
- ↑ مكتبة أدوات تويتر
- ↑ "Swift Async" . مؤرشف من الأصل في 31 ديسمبر 2018. تم الاطلاع عليه في 23 يونيو 2014 .
- ↑ Swift FutureKit
- ↑ Swift Apple GCD
- ↑ مكتبة Swift المستقبلية
- ↑ bignerdranch/مؤجل
- ↑ ثومفيس/برايت فيوتشرز
- ↑ belozierov/SwiftCoroutine
- ↑ وعد TCL
- ↑ هل يحل async/await مشكلة حقيقية؟
- ↑ "أنماط لغة Go المستقبلية" . مؤرشف من الأصل في 4 ديسمبر 2020. تم الاسترجاع في 9 فبراير 2014 .
- ↑ "أنماط لغة Go" . مؤرشف من الأصل في 11 نوفمبر 2020. تم الاطلاع عليه في 9 فبراير 2014 .
روابط خارجية
- التواصل بين العمليات
- نموذج الممثل (علوم الحاسوب)
