اكتساب الموارد تهيئة

اكتساب الموارد تهيئة Resource acquisition is initialization (RAII) [1] هو مصطلح برمجي [2] يستخدم في عدة لغات موجهة للكائنات لوصف سلوك لغوي معين. في RAII ، يعد الاحتفاظ بالمورد صنف غير متغيّر، ويرتبط بعمر الكائن: يتم تخصيص الموارد (أو اكتساب) أثناء إنشاء الكائن (على وجه التحديد التهيئة)، من قبل المنشئ، بينما يتم إلغاء تخصيص الموارد (التحرير/إصدار) أثناء تدمير الكائن (على وجه التحديد)، من قبل المدمرة. وبعبارة أخرى، يجب أن ينجح اكتساب الموارد حتى تنجح التهيئة. وبالتالي يتم ضمان الاحتفاظ بالمورد بين وقت انتهاء التهيئة وبدء الانتهاء (الاحتفاظ بالموارد هو صنف لا متغيّر)، ويتم الاحتفاظ به فقط عندما يكون الكائن على قيد الحياة. وبالتالي إذا لم يكن هناك أي تسرب للكائن، فلن يكون هناك تسرب للموارد.

يرتبط اكتساب الموارد تهيئة بشكل بارز بـ سي ++ حيث نشأ، ولكن أيضًا دي وأدا وفالا ورست. تم تطوير هذه التقنية لإدارة الموارد الآمنة للاستثناءات في سي ++ [3] خلال 1984-1989، بواسطةبيارن ستروستروب وأندرو كونيغ (كاتب) في المقام الأول، [3] والمصطلح نفسه صاغه ستروستروب (Stroustrup). [3] اكتساب الموارد تهيئة RAII تلفظ عموما باعتبارها initialism علامة اختصار، تلفظ في بعض الأحيان ب «R، A، I المزدوج».[4]

الأسماء الأخرى لهذا المصطلح تشمل اكتساب المُنشئ ، إصدارات المدمرة (CADRe) [5] وأحد أنماط الاستخدام المعينة يسمى إدارة الموارد المستندة إلى النطاق (SBRM).[6] هذا المصطلح الأخير للحالة الخاصة للمتغيرات التلقائية. يربط RAII الموارد بعمر الكائن ، والذي قد لا يتزامن مع الدخول والخروج من النطاق. (المتغيرات التي تم تخصيصها على المتجر المجاني بشكل خاص لها عمر لا علاقة له بأي مجال معين.) ومع ذلك، فإن استخدام RAII للمتغيرات التلقائية (SBRM) هو حالة الاستخدام الأكثر شيوعًا.

مثال C ++ 11 عدل

#include <fstream>
#include <iostream>
#include <mutex>
#include <stdexcept>
#include <string>

void WriteToFile(const std::string& message) {
 // |mutex| is to protect access to |file| (which is shared across threads).
 static std::mutex mutex;

 // Lock |mutex| before accessing |file|.
 std::lock_guard<std::mutex> lock(mutex);

 // Try to open file.
 std::ofstream file("example.txt");
 if (!file.is_open()) {
  throw std::runtime_error("unable to open file");
 }

 // Write |message| to |file|.
 file << message << std::endl;

 // |file| will be closed first when leaving scope (regardless of exception)
 // mutex will be unlocked second (from lock destructor) when leaving scope
 // (regardless of exception).
}

هذا الرمز آمن للاستثناء لأن سي ++ يضمن تدمير جميع كائنات المكدس stack في نهاية النطاق المضمن، والمعروف باسم فك المكدس. وبالتالي، يتم ضمان تدمير المدمرين لكل من كائنات القفل والملف عند الإرجاع من الدالة، سواء تم طرح استثناء أم لا.[7]

تسمح المتغيرات المحلية بإدارة سهلة لموارد متعددة داخل وظيفة واحدة: يتم تدميرها بالترتيب العكسي للبناء، ويتم تدمير الكائن فقط إذا تم بناؤه بالكامل — أي إذا لم يتم نشر استثناء من مُنشئه.[8]

يعمل استخدام RAII على تبسيط إدارة الموارد إلى حد كبير، ويقلل الحجم الكلي للرمز ويساعد على ضمان صحة البرنامج. لذا ينصح بشدة باستخدام RAII في سي ++، وتتبع معظم مكتبة سي ++ القياسية المصطلح.[9]

[ بحاجة لمصدر ]

العد المرجعي عدل

يدير بيرل وبايثون (في تنفيذ سي بايثون) و [10] وPHP [11] عمر الكائن عن طريق العد المرجعي، مما يجعل من الممكن استخدام RAII. الكائنات التي لم يعد مشار إليها يتم تدميرها على الفور أو انهائها وتحريرها، لذلك المدمر أوالمنهي يحرر الموارد في ذلك الوقت. ومع ذلك، فإنه ليس من المصطلح عليه دائما في مثل هذه اللغات، وغير منصوح به تحديدا في بايثون (لصالح مديري السياق وأدوات الإنهاء من حزمة weakref).

ومع ذلك، فإن عمر الكائن ليس بالضرورة مرتبطًا بأي نطاق، وقد يتم تدمير الكائنات بشكل غير حتمي أو لا يتم إطلاقها على الإطلاق. وهذا يجعل من الممكن تسريب الموارد عن طريق الخطأ التي كان ينبغي إطلاقها في نهاية نطاق ما. قد لا يتم انهاء الكائنات المخزنة في متغير ثابت (ولا سيما متغير عالمي) عندما ينتهي البرنامج، لذلك لا يتم تحرير مواردها؛ على سبيل المثال سي بايثون لا تقدم أي ضمان لإنهاء مثل هذه الكائنات. علاوة على ذلك، لن يتم جمع الكائنات ذات العناوين المرجعية الدائرية بواسطة عداد مرجعي بسيط، وسوف تعيش لفترة غير محددة؛ حتى إذا تم جمعها (عن طريق جمع القمامة الأكثر تعقيدًا)، فإن وقت التدمير وأمر التدمير سيكون غير حتمي. في سي بايثون هناك كاشف للحلقة والذي يحدد الحلقات وينهي الكائنات في الحلقة، على الرغم من أنه قبل سي بايثون 3.4، لم يتم تجميع الحلقات إذا كان أي كائن في الحلقة يحتوي على منهيات.[12]

المراجع عدل

  1. ^ Stroustrup، Bjarne (30 سبتمبر 2017). "Why doesn't C++ provide a "finally" construct?". مؤرشف من الأصل في 2020-07-02. اطلع عليه بتاريخ 2019-03-09.
  2. ^ Sutter، Herb؛ Alexandrescu، Andrei (2005). C++ Coding Standards. C++ In-Depth Series. Addison-Wesley. ص. 24. ISBN:978-0-321-11358-0. مؤرشف من الأصل في 2020-07-06.
  3. ^ أ ب ت Stroustrup 1994.
  4. ^ Michael Burr (19 سبتمبر 2008). "How do you pronounce RAII?". ستاك أوفرفلو. مؤرشف من الأصل في 2020-07-06. اطلع عليه بتاريخ 2019-03-09.
  5. ^ Arthur Tchaikovsky (6 نوفمبر 2012). "Change official RAII to CADRe". ISO C++ Standard - Future Proposals. مجموعات جوجل. مؤرشف من الأصل في 2020-07-06. اطلع عليه بتاريخ 2019-03-09.
  6. ^ Chou، Allen (1 أكتوبر 2014). "Scope-Based Resource Management (RAII)". مؤرشف من الأصل في 2020-05-10. اطلع عليه بتاريخ 2019-03-09.
  7. ^ "How can I handle a destructor that fails?". Standard C++ Foundation. مؤرشف من الأصل في 2020-04-25. اطلع عليه بتاريخ 2019-03-09.
  8. ^ Richard Smith (21 مارس 2017). "Working Draft, Standard for ProgrammingLanguage C++" (PDF). مؤرشف من الأصل (PDF) في 2019-11-24. اطلع عليه بتاريخ 2019-03-09.
  9. ^ "I have too many try blocks; what can I do about it?". Standard C++ Foundation. مؤرشف من الأصل في 2020-04-25. اطلع عليه بتاريخ 2019-03-09.
  10. ^ "Extending Python with C or C++: Reference Counts". Extending and Embedding the Python Interpreter. مؤسسة برمجيات بايثون. مؤرشف من الأصل في 2020-06-23. اطلع عليه بتاريخ 2019-03-09.
  11. ^ hobbs (8 فبراير 2011). "Does PHP support the RAII pattern? How?". مؤرشف من الأصل في 2020-07-06. اطلع عليه بتاريخ 2019-03-09.
  12. ^ "gc — Garbage Collector interface". The Python Standard Library. Python Software Foundation. مؤرشف من الأصل في 2020-06-17. اطلع عليه بتاريخ 2019-03-09.

قراءة متعمقة عدل

روابط خارجية عدل