التابع handle_interrupt
الخاص بالصنف Thread
في روبي
يغير التابع handle_interrupt
توقيت المقاطعة غير المتزامنة (asynchronous interrupt timing).
يعني interrupt
الحدث غير المتزامن (asynchronous event) والإجراء المقابل #raise
و #kill
، وإشارة المسك signal trap (غير مدعومة حاليًا)، وإنهاء المهمة الفرعية الرئيسية (عند إنهاء المهمة الفرعية الرئيسية، فسيتم إنهاء كل المهمة الفرعية الأخرى).
يتحتوي الوسيط المعطى hash
(انظر فقرة البنية العامة) أزواج على شاكلة ExceptionClass =>
TimingSymbol
. حيث ExceptionClass هو التوقيف (interrupt) الذي يعالج من قبل الكتلة المعطاة. يمكن أن يكون TimingSymbol أحد الرموز التالية:
:immediate
يستدعي التوقيفات على الفور.
:on_blocking
يستدعي التوقيفات أثناء BlockingOperation
.
:never
لا يستدعي جميع التوقيفات أبدا.
مصطلح BlockingOperation
يعني أن العملية ستقوم بتعطيل المهمة الفرعية المستدعية (calling thread)، مثل read و write. في إصدار CRuby ، ستكون BlockingOperation
أي عملية تنفذ بدون قفل الآلة الافتراضية العام (Global VM Lock أو اختصارًا GVL).
التوقيفات غير المتزامن المقنعة (Masked asynchronous interrupts) ستُؤجل إلى حين يتم تمكينها. هذا التابع مشابه للتابع sigprocmask (3).
يصعب استخدام التوقبفات غير المتزامنة.
إذا كنت بحاجة إلى إجراء اتصالات بين المهمة الفرعية، فالرجاء استخدام طريقة أخرى، مثل Queue
.
أو استخدمها هذا التابع، لكن مع فهم عميق لخصائصه.
في هذا المثال، يمكننا الاحتراز من استثناءات #raise
.
عند استخدام رمز التوقيت (TimingSymbol) :never
، سيتم تجاهل الاستثناء RuntimeError
دائما في الكتلة الأولى من المهمة الفرعية الرئيسية. في كتلة ::handle_interrupt
الثانية يمكن معالجة الاستثناءات RuntimeError
.
بينما نتجاهل الاستثناء RuntimeError
، سيكون من الآمن كتابة تعليمات تخصيص الموارد. بعد ذلك، تكون كتلة التأمين (ensure block) هي المكان الذي يمكننا فيه تحرير (deallocate ) الموارد بأمان.
التحرز من الاستثناء Timeout::Error
¶
↑
في المثال التالي، سنحترز من الاستثناء Timeout::Error. سيساعد هذا على منع هدر الموارد عند حدوث استثناء Timeout::Error أثناء كتلة تأمين (ensure clause) عادية. في هذا المثال، سنتعين بالمكتبة القياسي للمكتبة Timeout من lib/timeout.rb.
في الجزء الأول من كتلة timeout
، يمكننا الاعتماد على حقيقة أن Timeout::Error سيتم تجاهله. ثم في كتلة Timeout::Error =>
on_blocking
، أي عملية تعطل المهمة الفرعية المستدعية (calling thread) ستكون عرضة لاستثناء Timeout :: Error.
إعدادات التحكم في المكدس (Stack control settings)
¶
↑
من الممكن تكديس مستويات متعددة من كتل ::handle_interrupt
من أجل التحكم في عدة كائنات ExceptionClass و TimingSymbol في وقت واحد.
سيتم أخذ كافة الاستثناءات الموروثة من الوسيط ExceptionClass بعين الاعتبار.
البنية العامة
handle_interrupt(hash) { ... } → result of the block
المعاملات
hash
القيمة المُعادة
أمثلة
مثال على استخدام التابع handle_interrupt
:
th = Thread.new do
Thread.handle_interrupt(RuntimeError => :never) {
begin
# You can write resource allocation code safely.
Thread.handle_interrupt(RuntimeError => :immediate) {
# ...
}
ensure
# You can write resource deallocation code safely.
end
}
end
Thread.pass
# ...
th.raise "stop"
انظر أيضا
- التابع
fork
: أساسا، التابع التابعfork
مكافئ للتابع new. ومع ذلك ، في حال اشتقاق صنف فرعي من::new
، فإن استدعاءThread
في ذلك الصنف الفرعي لن يستدعي تابع الصنف الفرعيstart
. - التابع
kill
: بقوم التابعkill
بإنهاءthread
المعطى (انظر فقرة البنية العامة)، راجع أيضًا صفحة::exit
.