الفرق بين المراجعتين لصفحة: «Ruby/Thread/handle interrupt»

من موسوعة حسوب
< Ruby‏ | Thread
لا ملخص تعديل
ط مراجعة وتدقيق.
 
(مراجعة متوسطة واحدة بواسطة مستخدم واحد آخر غير معروضة)
سطر 1: سطر 1:
<noinclude>{{DISPLAYTITLE: التابع <code>handle_interrupt‎</code> الخاص بالصنف <code>Thread</code> في روبي}}</noinclude>
<noinclude>{{DISPLAYTITLE: التابع <code>Thread.handle_interrupt‎</code> في روبي}}</noinclude>
[[تصنيف: Ruby]]
[[تصنيف: Ruby]]
[[تصنيف: Ruby Method]]
[[تصنيف: Ruby Method]]
[[تصنيف: Ruby Thread]]
[[تصنيف: Ruby Thread]]
يغير التابع <code>handle_interrupt</code> توقيت التوقيف غير المتزامن (asynchronous interrupt timing).
يغير التابع <code>handle_interrupt</code> توقيت المقاطعة غير المتزامنة (asynchronous interrupt timing).


التوقيف (interrupt ) يعني الحدث غير المتزامن (asynchronous event) والإجراء المقابل <code>[[Ruby/Thread/raise|raise]]</code> و <code>[[Ruby/Thread/kill|kill]]</code> وإشارة المسك signal trap (غير مدعومة حاليًا) وعملية إنهاء [[Ruby/Thread|المهمة الفرعية]] الرئيسية (عند إنهاء [[Ruby/Thread|المهمة الفرعية]] الرئيسية، فسيتم إنهاء كل [[Ruby/Thread|المهام الفرعية]] الأخرى).
المقاطعة (interrupt) يعني الحدث غير المتزامن (asynchronous event) والإجراء المقابل <code>[[Ruby/Thread/raise|raise]]</code> و <code>[[Ruby/Thread/kill|kill]]</code> وإشارة المسك (signal trap، غير مدعومة حاليًا) وعملية إنهاء [[Ruby/Thread|المهمة الفرعية]] الرئيسية (عند إنهاء [[Ruby/Thread|المهمة الفرعية]] الرئيسية، فسيتم إنهاء كل [[Ruby/Thread|المهام الفرعية]] الأخرى).
 
==البنية العامة==
يحتوي الوسيط المعطى <code>hash</code> (انظر فقرة البنية العامة) أزواج على شاكلة <code>ExceptionClass => :TimingSymbol</code>. حيث <code>ExceptionClass</code> هو التوقيف (interrupt) المٌعالج من قبل الكتلة المعطاة. أما <code>TimingSymbol</code> فيمكن أن يكون  أحد الرموز التالية:
<syntaxhighlight lang="ruby">handle_interrupt(hash) { ... } → result of the block‎</syntaxhighlight>يحتوي المعامل <code>hash</code> المعطى على أزواج على شاكلة <code>ExceptionClass => :TimingSymbol</code> إذ <code>ExceptionClass</code> هو مقاطعة (interrupt) المٌعالج من قبل الكتلة المعطاة. أما <code>TimingSymbol</code> فيمكن أن يكون  أحد الرموز التالية:
* ‎<code>:immediate</code> - يستدعي التوقيفات على الفور.
* ‎<code>:immediate</code> - يستدعي المقاطعات على الفور.
* ‎<code>:on_blocking</code> - يستدعي التوقيفات أثناء الحالة <code>BlockingOperation</code>.
* ‎<code>:on_blocking</code> - يستدعي المقاطعات أثناء الحالة <code>BlockingOperation</code>.
* ‎<code>:never</code> - لا يستدعي جميع التوقيفات أبدا.
* ‎<code>:never</code> - لا يستدعي جميع المقاطعات أبدًا.
مصطلح <code>BlockingOperation</code> يعني أن العملية ستقوم بتعطيل [[Ruby/Thread|المهمة الفرعية]] المستدعية (calling thread)، مثل <code>read</code> و <code>write</code>.  في إصدار CRuby ، س​​تكون <code>BlockingOperation</code> أي عملية تنفذ بدون قفل الآلة الافتراضية العام (Global VM Lock أو اختصارًا GVL).
<code>BlockingOperation</code> تعني أن العملية ستقوم بتعطيل [[Ruby/Thread|المهمة الفرعية]] المستدعية (calling thread)، مثل <code>read</code> و <code>write</code>.  في إصدار CRuby ، س​​تكون <code>BlockingOperation</code> أي عملية تُنفَّذ بدون قفل الآلة الافتراضية العام (Global VM Lock أو اختصارًا GVL).
 
التوقيفات غير المتزامنة المقنعة (Masked asynchronous interrupts) ستُؤجل إلى حين تمكينها.  


هذا التابع مشابه للتعبير<code>sigprocmask(3)‎</code>.
المقاطعات غير المتزامنة المقنعة (Masked asynchronous interrupts) ستُؤجل إلى حين تمكينها.  


'''ملحوظة'''
هذا التابع مشابه للتعبير <code>sigprocmask(3)‎</code>.


يصعب استخدام التوقبفات غير المتزامنة.
== ملاحظة ==
 
يصعب استخدام المقاطعات غير المتزامنة. إذا كنت بحاجة إلى إجراء اتصالات بين [[Ruby/Thread|المهام الفرعية]]، فالرجاء استخدام طريقة أخرى، مثل [[Ruby/Queue|الطوابير]]. وإن كنت مصرّا على استخدام هذا التابع، فاستخدمه، لكن مع فهم عميق لخصائصه.
إذا كنت بحاجة إلى إجراء اتصالات بين [[Ruby/Thread|المهام الفرعية]]، فالرجاء استخدام طريقة أخرى، مثل الطوابير (<code>[[Ruby/Queue|Queues]])</code>.
 
وإن كنت مصرّا على استخدام هذا التابع، فاستخدمه، لكن مع فهم عميق لخصائصه.


== الاستخدام ==
== الاستخدام ==
في هذا المثال، يمكننا الاحتراز من استثناءات <code>[[Ruby/Thread/raise|#raise]]</code>.
في المثال التالي، يمكننا الاحتراز من استثناءات <code>[[Ruby/Thread/raise|raise]]</code>.
 
عند استخدام رمز التوقيت (TimingSymbol‏) <code>:never</code>، سيتم تجاهل الاستثناء <code>[[Ruby/RuntimeError|RuntimeError]]</code> دائما في الكتلة الأولى من [[Ruby/Thread|المهمة الفرعية]] الرئيسية. في كتلة <code>[[Ruby/Thread/handle_interrupt|::handle_interrupt]]</code> الثانية يمكن معالجة الاستثناءات <code>[[Ruby/RuntimeError|RuntimeError]]</code>.
 
 
 
بينما نتجاهل الاستثناء <code>[[Ruby/RuntimeError|RuntimeError]]</code>، سيكون من الآمن كتابة تعليمات تخصيص الموارد. بعد ذلك، تكون كتلة التأمين (ensure block) هي المكان الذي يمكننا فيه تحرير (deallocate ) الموارد بأمان.
 
التحرز من الاستثناء Timeout::Error
<code>[[Ruby//handle_interrupt-label-Guarding+from+Timeout-3A-3AError|¶]]</code> <code>[[Ruby//top|↑]]</code>
 
في المثال التالي، سنحترز من الاستثناء Timeout::Error. سيساعد هذا على منع هدر الموارد عند حدوث استثناء Timeout::Error أثناء كتلة تأمين (ensure clause) عادية. في هذا المثال، سنتعين بالمكتبة القياسي للمكتبة Timeout من lib/timeout.rb.
 
 
 
في الجزء الأول من كتلة <code>timeout</code> ، يمكننا الاعتماد على حقيقة أن Timeout::Error سيتم تجاهله. ثم في كتلة <code>Timeout::Error =>
:on_blocking</code>، أي عملية تعطل [[Ruby/Thread|المهمة الفرعية]] المستدعية (calling thread) ستكون عرضة لاستثناء Timeout :: Error.
 
إعدادات التحكم في المكدس (Stack control settings)
<code>[[Ruby//handle_interrupt-label-Stack+control+settings|¶]]</code> <code>[[Ruby//top|↑]]</code>
 
من الممكن تكديس مستويات متعددة من كتل <code>[[Ruby/Thread/handle_interrupt|::handle_interrupt]]</code> من أجل التحكم في عدة كائنات ExceptionClass و TimingSymbol في وقت واحد.
 


 
باستخدام رمز التوقيت (TimingSymbol‏) ‎<code>:never</code>، سيتم تجاهل الاستثناء <code>[[Ruby/RuntimeError|RuntimeError]]</code> دائما في الكتلة الأولى من [[Ruby/Thread|المهمة الفرعية]] الرئيسية. في كتلة <code>handle_interrupt</code> الثانية، يمكن معالجة الاستثناءات <code>[[Ruby/RuntimeError|RuntimeError]]</code>:<syntaxhighlight lang="ruby">th = Thread.new do
الوراثة من ExceptionClass
<code>[[Ruby//handle_interrupt-label-Inheritance+with+ExceptionClass|¶]]</code> <code>[[Ruby//top|]]</code>
 
سيتم أخذ كافة الاستثناءات الموروثة من الوسيط ExceptionClass بعين الاعتبار.
==البنية العامة==
<syntaxhighlight lang="ruby">handle_interrupt(hash) { ... } → result of the block‎</syntaxhighlight>
==المعاملات==
===<code>hash‎</code>===
==القيمة المُعادة==
==أمثلة==
مثال على استخدام التابع <code>handle_interrupt‎</code>:
<syntaxhighlight lang="ruby">th = Thread.new do
   Thread.handle_interrupt(RuntimeError => :never) {
   Thread.handle_interrupt(RuntimeError => :never) {
     begin
     begin
سطر 76: سطر 37:
Thread.pass
Thread.pass
# ...
# ...
th.raise "stop"‎</syntaxhighlight>
th.raise "stop"‎</syntaxhighlight>بينما نتجاهل الاستثناء <code>[[Ruby/RuntimeError|RuntimeError]]</code>، سيكون من الآمن كتابة تعليمات تخصيص الموارد (resource allocation). بعد ذلك ستكون كتلة التأمين (ensure block) هي المكان المناسب لتحرير (deallocate) الموارد بأمان.
==انظر أيضا==
 
* التابع <code>[[Ruby/Thread/fork|fork]]</code>: أساسا، التابع التابع <code>fork</code> مكافئ للتابع new. ومع ذلك ، في حال اشتقاق صنف فرعي من <code>[[Ruby/Thread/new|::new]]</code>، فإن استدعاء <code>[[Ruby/Thread|Thread]]</code> في ذلك الصنف الفرعي لن يستدعي تابع الصنف الفرعي <code>[[Ruby/Thread/start|start]]</code>.
== التحرز من الاستثناء <code>Timeout::Error</code> ==
* التابع <code>[[Ruby/Thread/kill|kill]]</code>: بقوم التابع <code>kill</code> بإنهاء <code>thread</code> المعطى (انظر فقرة البنية العامة)، راجع أيضًا صفحة <code>[[Ruby/Thread/exit|::exit]]</code>.
في المثال التالي، سنحترز من الاستثناء <code>Timeout::Error</code>. سيساعد هذا على منع هدر الموارد عند حدوث هذا الاستثناء أثناء كتلة تأمين (ensure clause) عادية. في هذا المثال، سنستعين بالمكتبة القياسية <code>Timeout</code> في <code>lib/timeout.rb</code>.<syntaxhighlight lang="ruby">require 'timeout'
Thread.handle_interrupt(Timeout::Error => :never) {
  timeout(10){
    # Timeout::Error doesn't occur here
    Thread.handle_interrupt(Timeout::Error => :on_blocking) {
      # possible to be killed by Timeout::Error
      # while blocking operation
    }
    # Timeout::Error doesn't occur here
  }
}</syntaxhighlight>في الجزء الأول من كتلة <code>timeout</code> ، يمكننا الاعتماد على حقيقة أن الاستثناء <code>Timeout::Error</code> سيتم تجاهله. ثم في كتلة <code>Timeout::Error =>on_blocking</code>، فأي عملية تُعطل [[Ruby/Thread|المهمة الفرعية]] المستدعية (calling thread) ستكون عرضة للاستثناء <code>Timeout::Error</code>.
 
== إعدادات التحكم في المكدس ==
من الممكن تكديس مستويات متعددة من كتل <code>handle_interrupt</code> من أجل التحكم في عدة كائنات من النوع <code>ExceptionClass</code> و <code>TimingSymbol</code> في وقت واحد.<syntaxhighlight lang="ruby">Thread.handle_interrupt(FooError => :never) {
  Thread.handle_interrupt(BarError => :never) {
    # FooError and BarError are prohibited.
  }
}</syntaxhighlight>
 
== الوراثة من <code>ExceptionClass</code> ==
سيتم أخذ كافة الاستثناءات الموروثة من الوسيط <code>ExceptionClass</code> بعين الاعتبار.
<syntaxhighlight lang="ruby">Thread.handle_interrupt(Exception => :never) {
  # all exceptions inherited from Exception are prohibited.
}</syntaxhighlight>
==القيمة المُعادة==
تعاد نتيجة الكتلة المعطاة.
 
==انظر أيضًا==
* التابع <code>[[Ruby/Thread/fork|fork]]</code>: ينشئ عملية فرعية جديدة بشكل مكافئ للتابع <code>new</code>.
* التابع <code>[[Ruby/Thread/kill|kill]]</code>: ينهي العملية الفرعية المعطاة.
==مصادر==
==مصادر==
*[http://ruby-doc.org/core-2.5.1/Thread.html#method-c-handle_interrupt قسم التابع handle_interrupt‎ في الصنف Thread‎ في توثيق روبي الرسمي.]
*[http://ruby-doc.org/core-2.5.1/Thread.html#method-c-handle_interrupt قسم التابع handle_interrupt‎ في الصنف Thread‎ في توثيق روبي الرسمي.]

المراجعة الحالية بتاريخ 12:22، 5 ديسمبر 2018

يغير التابع handle_interrupt توقيت المقاطعة غير المتزامنة (asynchronous interrupt timing).

المقاطعة (interrupt) يعني الحدث غير المتزامن (asynchronous event) والإجراء المقابل raise و kill وإشارة المسك (signal trap، غير مدعومة حاليًا) وعملية إنهاء المهمة الفرعية الرئيسية (عند إنهاء المهمة الفرعية الرئيسية، فسيتم إنهاء كل المهام الفرعية الأخرى).

البنية العامة

handle_interrupt(hash) { ... }  result of the block

يحتوي المعامل 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)‎.

ملاحظة

يصعب استخدام المقاطعات غير المتزامنة. إذا كنت بحاجة إلى إجراء اتصالات بين المهام الفرعية، فالرجاء استخدام طريقة أخرى، مثل الطوابير. وإن كنت مصرّا على استخدام هذا التابع، فاستخدمه، لكن مع فهم عميق لخصائصه.

الاستخدام

في المثال التالي، يمكننا الاحتراز من استثناءات raise.

باستخدام رمز التوقيت (TimingSymbol‏) ‎:never، سيتم تجاهل الاستثناء RuntimeError دائما في الكتلة الأولى من المهمة الفرعية الرئيسية. في كتلة handle_interrupt الثانية، يمكن معالجة الاستثناءات RuntimeError:

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"

بينما نتجاهل الاستثناء RuntimeError، سيكون من الآمن كتابة تعليمات تخصيص الموارد (resource allocation). بعد ذلك ستكون كتلة التأمين (ensure block) هي المكان المناسب لتحرير (deallocate) الموارد بأمان.

التحرز من الاستثناء Timeout::Error

في المثال التالي، سنحترز من الاستثناء Timeout::Error. سيساعد هذا على منع هدر الموارد عند حدوث هذا الاستثناء أثناء كتلة تأمين (ensure clause) عادية. في هذا المثال، سنستعين بالمكتبة القياسية Timeout في lib/timeout.rb.

require 'timeout'
Thread.handle_interrupt(Timeout::Error => :never) {
  timeout(10){
    # Timeout::Error doesn't occur here
    Thread.handle_interrupt(Timeout::Error => :on_blocking) {
      # possible to be killed by Timeout::Error
      # while blocking operation
    }
    # Timeout::Error doesn't occur here
  }
}

في الجزء الأول من كتلة timeout ، يمكننا الاعتماد على حقيقة أن الاستثناء Timeout::Error سيتم تجاهله. ثم في كتلة Timeout::Error =>on_blocking، فأي عملية تُعطل المهمة الفرعية المستدعية (calling thread) ستكون عرضة للاستثناء Timeout::Error.

إعدادات التحكم في المكدس

من الممكن تكديس مستويات متعددة من كتل handle_interrupt من أجل التحكم في عدة كائنات من النوع ExceptionClass و TimingSymbol في وقت واحد.

Thread.handle_interrupt(FooError => :never) {
  Thread.handle_interrupt(BarError => :never) {
     # FooError and BarError are prohibited.
  }
}

الوراثة من ExceptionClass

سيتم أخذ كافة الاستثناءات الموروثة من الوسيط ExceptionClass بعين الاعتبار.

Thread.handle_interrupt(Exception => :never) {
  # all exceptions inherited from Exception are prohibited.
}

القيمة المُعادة

تعاد نتيجة الكتلة المعطاة.

انظر أيضًا

  • التابع fork: ينشئ عملية فرعية جديدة بشكل مكافئ للتابع new.
  • التابع kill: ينهي العملية الفرعية المعطاة.

مصادر