mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* thread.c: Improved rdoc for ::handle_interrupt, ::pending_interrupt?
and #pending_interrupt? git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@39428 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
4abd941e78
commit
5f2e433813
2 changed files with 73 additions and 38 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
Sat Feb 23 16:00:00 2013 Zachary Scott <zachary@zacharyscott.net>
|
||||||
|
|
||||||
|
* thread.c: Improved rdoc for ::handle_interrupt, ::pending_interrupt?
|
||||||
|
and #pending_interrupt?
|
||||||
|
|
||||||
Sat Feb 23 12:26:43 2013 Akinori MUSHA <knu@iDaemons.org>
|
Sat Feb 23 12:26:43 2013 Akinori MUSHA <knu@iDaemons.org>
|
||||||
|
|
||||||
* misc/ruby-electric.el (ruby-electric-curlies)
|
* misc/ruby-electric.el (ruby-electric-curlies)
|
||||||
|
|
106
thread.c
106
thread.c
|
@ -1585,49 +1585,53 @@ handle_interrupt_arg_check_i(VALUE key, VALUE val)
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* Thread.handle_interrupt(hash) { ... } -> result of the block
|
* Thread.handle_interrupt(hash) { ... } -> result of the block
|
||||||
*
|
*
|
||||||
* Thread.Thread#handle_interrupt changes async interrupt timing.
|
* Changes asynchronous interrupt timing.
|
||||||
*
|
*
|
||||||
* _interrupt_ means asynchronous event and corresponding procedure
|
* _interrupt_ means asynchronous event and corresponding procedure
|
||||||
* by Thread#raise, Thread#kill, signal trap (not supported yet)
|
* by Thread#raise, Thread#kill, signal trap (not supported yet)
|
||||||
* and main thread termination (if main thread terminates, then all
|
* and main thread termination (if main thread terminates, then all
|
||||||
* other thread will be killed).
|
* other thread will be killed).
|
||||||
*
|
*
|
||||||
* _hash_ has pairs of ExceptionClass and TimingSymbol. TimingSymbol
|
* The given +hash+ has pairs like <code>ExceptionClass =>
|
||||||
* is one of them:
|
* :TimingSymbol</code>. Where the ExceptionClass is the interrupt handled by
|
||||||
* - :immediate Invoke interrupts immediately.
|
* the given block. The TimingSymbol can be one of the following symbols:
|
||||||
* - :on_blocking Invoke interrupts while _BlockingOperation_.
|
*
|
||||||
* - :never Never invoke all interrupts.
|
* [+:immediate+] Invoke interrupts immediately.
|
||||||
|
* [+:on_blocking+] Invoke interrupts while _BlockingOperation_.
|
||||||
|
* [+:never+] Never invoke all interrupts.
|
||||||
*
|
*
|
||||||
* _BlockingOperation_ means that the operation will block the calling thread,
|
* _BlockingOperation_ means that the operation will block the calling thread,
|
||||||
* such as read and write. On CRuby implementation, _BlockingOperation_ is
|
* such as read and write. On CRuby implementation, _BlockingOperation_ is any
|
||||||
* operation executed without GVL.
|
* operation executed without GVL.
|
||||||
*
|
*
|
||||||
* Masked async interrupts are delayed until they are enabled.
|
* Masked asynchronous interrupts are delayed until they are enabled.
|
||||||
* This method is similar to sigprocmask(3).
|
* This method is similar to sigprocmask(3).
|
||||||
*
|
*
|
||||||
* TODO (DOC): Thread#handle_interrupt is stacked.
|
* === NOTE
|
||||||
* TODO (DOC): check ancestors.
|
|
||||||
* TODO (DOC): to prevent all async interrupt, {Object => :never} works.
|
|
||||||
*
|
*
|
||||||
* NOTE: Asynchronous interrupts are difficult to use.
|
* Asynchronous interrupts are difficult to use.
|
||||||
* If you need to communicate between threads,
|
|
||||||
* please consider to use another way such as Queue.
|
|
||||||
* Or use them with deep understanding about this method.
|
|
||||||
*
|
*
|
||||||
|
* If you need to communicate between threads, please consider to use another way such as Queue.
|
||||||
|
*
|
||||||
|
* Or use them with deep understanding about this method.
|
||||||
|
*
|
||||||
|
* === Usage
|
||||||
|
*
|
||||||
|
* In this example, we can guard from Thread#raise exceptions.
|
||||||
|
*
|
||||||
|
* Using the +:never+ TimingSymbol the RuntimeError exception will always be
|
||||||
|
* ignored in the first block of the main thread. In the second
|
||||||
|
* ::handle_interrupt block we can purposefully handle RuntimeError exceptions.
|
||||||
*
|
*
|
||||||
* # example: Guard from Thread#raise
|
|
||||||
* th = Thread.new do
|
* th = Thread.new do
|
||||||
* Thead.handle_interrupt(RuntimeError => :never) {
|
* Thead.handle_interrupt(RuntimeError => :never) {
|
||||||
* begin
|
* begin
|
||||||
* # Thread#raise doesn't async interrupt here.
|
|
||||||
* # You can write resource allocation code safely.
|
* # You can write resource allocation code safely.
|
||||||
* Thread.handle_interrupt(RuntimeError => :immediate) {
|
* Thread.handle_interrupt(RuntimeError => :immediate) {
|
||||||
* # ...
|
* # ...
|
||||||
* # It is possible to be interrupted by Thread#raise.
|
|
||||||
* }
|
* }
|
||||||
* ensure
|
* ensure
|
||||||
* # Thread#raise doesn't interrupt here.
|
* # You can write resource deallocation code safely.
|
||||||
* # You can write resource dealocation code safely.
|
|
||||||
* end
|
* end
|
||||||
* }
|
* }
|
||||||
* end
|
* end
|
||||||
|
@ -1635,7 +1639,17 @@ handle_interrupt_arg_check_i(VALUE key, VALUE val)
|
||||||
* # ...
|
* # ...
|
||||||
* th.raise "stop"
|
* th.raise "stop"
|
||||||
*
|
*
|
||||||
* # example: Guard from TimeoutError
|
* While we are ignoring the RuntimeError exception, it's safe to write our
|
||||||
|
* resource allocation code. Then in the ensure block is where you can safely
|
||||||
|
* deallocate your resources.
|
||||||
|
*
|
||||||
|
* ==== Guarding from TimeoutError
|
||||||
|
*
|
||||||
|
* In the next example, we will guard from the TimeoutError exception. This
|
||||||
|
* will help prevent from leaking resources when TimeoutError exceptions occur
|
||||||
|
* during normal ensure clause. For this example we use the help of the
|
||||||
|
* standard library Timeout, from lib/timeout.rb
|
||||||
|
*
|
||||||
* require 'timeout'
|
* require 'timeout'
|
||||||
* Thread.handle_interrupt(TimeoutError => :never) {
|
* Thread.handle_interrupt(TimeoutError => :never) {
|
||||||
* timeout(10){
|
* timeout(10){
|
||||||
|
@ -1648,14 +1662,26 @@ handle_interrupt_arg_check_i(VALUE key, VALUE val)
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* # example: Stack control settings
|
* In the first part of the +timeout+ block, we can rely on TimeoutError being
|
||||||
|
* ignored. Then in the <code>TimeoutError => :on_blocking</code> block, any
|
||||||
|
* operation that will block the calling thread is susceptible to a
|
||||||
|
* TimeoutError exception being raised.
|
||||||
|
*
|
||||||
|
* ==== Stack control settings
|
||||||
|
*
|
||||||
|
* It's possible to stack multiple levels of ::handle_interrupt blocks in order
|
||||||
|
* to control more than one ExceptionClass and TimingSymbol at a time.
|
||||||
|
*
|
||||||
* Thread.handle_interrupt(FooError => :never) {
|
* Thread.handle_interrupt(FooError => :never) {
|
||||||
* Thread.handle_interrupt(BarError => :never) {
|
* Thread.handle_interrupt(BarError => :never) {
|
||||||
* # FooError and BarError are prohibited.
|
* # FooError and BarError are prohibited.
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* # example: check ancestors
|
* ==== Inheritance with ExceptionClass
|
||||||
|
*
|
||||||
|
* All exceptions inherited from the ExceptionClass parameter will be considered.
|
||||||
|
*
|
||||||
* Thread.handle_interrupt(Exception => :never) {
|
* Thread.handle_interrupt(Exception => :never) {
|
||||||
* # all exceptions inherited from Exception are prohibited.
|
* # all exceptions inherited from Exception are prohibited.
|
||||||
* }
|
* }
|
||||||
|
@ -1704,9 +1730,13 @@ rb_thread_s_handle_interrupt(VALUE self, VALUE mask_arg)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* target_thread.pending_interrupt?(err = nil) -> true/false
|
* target_thread.pending_interrupt?(error = nil) -> true/false
|
||||||
*
|
*
|
||||||
* Check async queue is empty or not.
|
* Returns whether or not the asychronous queue is empty for the target thread.
|
||||||
|
*
|
||||||
|
* If +error+ is given, then check only for +error+ type deferred events.
|
||||||
|
*
|
||||||
|
* See ::pending_interrupt? for more information.
|
||||||
*/
|
*/
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_thread_pending_interrupt_p(int argc, VALUE *argv, VALUE target_thread)
|
rb_thread_pending_interrupt_p(int argc, VALUE *argv, VALUE target_thread)
|
||||||
|
@ -1738,17 +1768,17 @@ rb_thread_pending_interrupt_p(int argc, VALUE *argv, VALUE target_thread)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* Thread.pending_interrupt?(err = nil) -> true/false
|
* Thread.pending_interrupt?(error = nil) -> true/false
|
||||||
*
|
*
|
||||||
* Check async queue is empty or not.
|
* Returns whether or not the asynchronous queue is empty.
|
||||||
*
|
*
|
||||||
* Thread.handle_interrupt can defer asynchronous events.
|
* Since Thread::handle_interrupt can be used to defer asynchronous events.
|
||||||
* This method returns deferred event are there.
|
* This method can be used to determine if there are any deferred events.
|
||||||
* If you find this method return true, then you may finish
|
|
||||||
* never block.
|
|
||||||
*
|
*
|
||||||
* For example, the following method processes defferred async event
|
* If you find this method returns true, then you may finish +:never+ blocks.
|
||||||
* immediately.
|
*
|
||||||
|
* For example, the following method processes deferred asynchronous events
|
||||||
|
* immediately.
|
||||||
*
|
*
|
||||||
* def Thread.kick_interrupt_immediately
|
* def Thread.kick_interrupt_immediately
|
||||||
* Thread.handle_interrupt(Object => :immediate) {
|
* Thread.handle_interrupt(Object => :immediate) {
|
||||||
|
@ -1756,9 +1786,9 @@ rb_thread_pending_interrupt_p(int argc, VALUE *argv, VALUE target_thread)
|
||||||
* }
|
* }
|
||||||
* end
|
* end
|
||||||
*
|
*
|
||||||
* If _err_ is given, then check only _err_ async interrupts.
|
* If +error+ is given, then check only for +error+ type deferred events.
|
||||||
*
|
*
|
||||||
* Examples:
|
* === Usage
|
||||||
*
|
*
|
||||||
* th = Thread.new{
|
* th = Thread.new{
|
||||||
* Thread.handle_interrupt(RuntimeError => :on_blocking){
|
* Thread.handle_interrupt(RuntimeError => :on_blocking){
|
||||||
|
@ -1775,8 +1805,8 @@ rb_thread_pending_interrupt_p(int argc, VALUE *argv, VALUE target_thread)
|
||||||
* ...
|
* ...
|
||||||
* th.raise # stop thread
|
* th.raise # stop thread
|
||||||
*
|
*
|
||||||
* NOTE: This example can be described by the another code.
|
* This example can also be written as the following, which you should use to
|
||||||
* You need to keep to avoid asynchronous interrupts.
|
* avoid asynchronous interrupts.
|
||||||
*
|
*
|
||||||
* flag = true
|
* flag = true
|
||||||
* th = Thread.new{
|
* th = Thread.new{
|
||||||
|
|
Loading…
Add table
Reference in a new issue