mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* vm.c (Thread): Documentation overview of Thread class
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@39521 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
f7a7138d5b
commit
ab0d28c1bd
2 changed files with 151 additions and 1 deletions
|
@ -1,3 +1,7 @@
|
|||
Wed Feb 27 13:02:00 2013 Zachary Scott <zachary@zacharyscott.net>
|
||||
|
||||
* vm.c (Thread): Documentation overview of Thread class
|
||||
|
||||
Wed Feb 27 12:57:00 2013 Zachary Scott <zachary@zacharyscott.net>
|
||||
|
||||
* thread.c (rb_thread_wakeup): rdoc formatting
|
||||
|
|
148
vm.c
148
vm.c
|
@ -2241,7 +2241,153 @@ Init_VM(void)
|
|||
rb_undef_alloc_func(rb_cEnv);
|
||||
rb_undef_method(CLASS_OF(rb_cEnv), "new");
|
||||
|
||||
/* ::Thread */
|
||||
/*
|
||||
* Document-class: Thread
|
||||
*
|
||||
* Threads are the Ruby implementation for a concurrent programming model.
|
||||
*
|
||||
* Programs that require multiple threads of execution are a perfect
|
||||
* candidate for Ruby's Thread class.
|
||||
*
|
||||
* For example, we can create a new thread separate from the main thread's
|
||||
* execution using ::new.
|
||||
*
|
||||
* thr = Thread.new { puts "Whats the big deal" }
|
||||
*
|
||||
* Then we are able to pause the execution of the main thread and allow
|
||||
* our new thread to finish, using #join:
|
||||
*
|
||||
* thr.join #=> "Whats the big deal"
|
||||
*
|
||||
* If we don't call +thr.join+ before the main thread terminates, then all
|
||||
* other threads including +thr+ will be killed.
|
||||
*
|
||||
* Alternatively, you can use an array for handling multiple threads at
|
||||
* once, like in the following example:
|
||||
*
|
||||
* threads = []
|
||||
* threads << Thread.new { puts "Whats the big deal" }
|
||||
* threads << Thread.new { 3.times { puts "Threads are fun!" } }
|
||||
*
|
||||
* After creating a few threads we wait for them all to finish
|
||||
* consecutively.
|
||||
*
|
||||
* threads.each { |thr| thr.join }
|
||||
*
|
||||
* === Thread initialization
|
||||
*
|
||||
* In order to create new threads, Ruby provides ::new, ::start, and
|
||||
* ::fork. A block must be provided with each of these methods, otherwise
|
||||
* a ThreadError will be raised.
|
||||
*
|
||||
* When subclassing the Thread class, the +initialize+ method of your
|
||||
* subclass will be ignored by ::start and ::fork. Otherwise, be sure to
|
||||
* call super in your +initialize+ method.
|
||||
*
|
||||
* === Thread termination
|
||||
*
|
||||
* For terminating threads, Ruby provides a variety of ways to do this.
|
||||
*
|
||||
* The class method ::kill, is meant to exit a given thread:
|
||||
*
|
||||
* thr = Thread.new { ... }
|
||||
* Thread.kill(thr) # sends exit() to thr
|
||||
*
|
||||
* Alternatively, you can use the instance method #exit, or any of it's
|
||||
* aliases #kill or #terminate.
|
||||
*
|
||||
* thr.exit
|
||||
*
|
||||
* === Thread status
|
||||
*
|
||||
* Ruby provides a few instance methods for querying the state of a given
|
||||
* thread. To get a string with a thread's current state use #status
|
||||
*
|
||||
* thr = Thread.new { sleep }
|
||||
* thr.status # => "sleep"
|
||||
* thr.exit
|
||||
* thr.status # => "false"
|
||||
*
|
||||
* You can also use #alive? to tell if the thread is running or sleeping,
|
||||
* and #stop? if the thread is dead or sleeping.
|
||||
*
|
||||
* === Thread variables and scope
|
||||
*
|
||||
* Since threads are created with blocks, the same rules apply to other
|
||||
* Ruby blocks for variable scope. Any local variables created within this
|
||||
* block are accessible to only this thread.
|
||||
*
|
||||
* ==== Fiber-local vs. Thread-local
|
||||
*
|
||||
* Each fiber has it's own bucket for Thread#[] storage, when you set a
|
||||
* new fiber-local it is only accessible within this Fiber. To illustrate:
|
||||
*
|
||||
* Thread.new {
|
||||
* Thread.current[:foo] = "bar"
|
||||
* Fiber.new {
|
||||
* p Thread.current[:foo] # => nil
|
||||
* }.resume
|
||||
* }.join
|
||||
*
|
||||
* This example uses #[] for setting and #[]= for getting fiber-locals,
|
||||
* you can also use #keys to list the fiber-locals for a given
|
||||
* thread and #key? to check if a fiber-local exists.
|
||||
*
|
||||
* When it comes to thread-locals, they are accessible within the entire
|
||||
* scope of the thread. Given the following example:
|
||||
*
|
||||
* Thread.new{
|
||||
* Thread.current.thread_variable_set(:foo, 1)
|
||||
* p Thread.current.thread_variable_get(:foo) # => 1
|
||||
* Fiber.new{
|
||||
* Thread.current.thread_variable_set(:foo, 2)
|
||||
* p Thread.current.thread_variable_get(:foo) # => 2
|
||||
* }.resume
|
||||
* p Thread.current.thread_variable_get(:foo) # => 2
|
||||
* }.join
|
||||
*
|
||||
* You can see that the thread-local +:foo+ carried over into the fiber
|
||||
* and was changed to +2+ by the end of the thread.
|
||||
*
|
||||
* This example makes use of #thread_variable_set to create new
|
||||
* thread-locals, and #thread_variable_get to reference them.
|
||||
*
|
||||
* There is also #thread_variables to list all thread-locals, and
|
||||
* #thread_variable? to check if a given thread-local exists.
|
||||
*
|
||||
* === Exception handling
|
||||
*
|
||||
* Any thread can raise an exception using the #raise instance method,
|
||||
* which operates similarly to Kernel#raise.
|
||||
*
|
||||
* However, it's important to note that an exception that occurs in any
|
||||
* thread except the main thread depends on #abort_on_exception. This
|
||||
* option is +false+ by default, meaning that any unhandled exception will
|
||||
* cause the thread to terminate silently when waited on by either #join
|
||||
* or #value. You can change this default by either #abort_on_exception=
|
||||
* +true+ or setting $DEBUG to +true+.
|
||||
*
|
||||
* With the addition of the class method ::handle_interrupt, you can now
|
||||
* handle exceptions asynchronously with threads.
|
||||
*
|
||||
* === Scheduling
|
||||
*
|
||||
* Ruby provides a few ways to support scheduling threads in your program.
|
||||
*
|
||||
* The first way is by using the class method ::stop, to put the current
|
||||
* running thread to sleep and schedule the execution of another thread.
|
||||
*
|
||||
* Once a thread is asleep, you can use the instance method #wakeup to
|
||||
* mark your thread as eligible for scheduling.
|
||||
*
|
||||
* You can also try ::pass, which attempts to pass execution to another
|
||||
* thread but is dependent on the OS whether a running thread will switch
|
||||
* or not. The same goes for #priority, which let's you hint to the thread
|
||||
* scheduler which threads you want to take precedence when passing
|
||||
* execution. This method is also dependent on the OS and may be ignored
|
||||
* on some platforms.
|
||||
*
|
||||
*/
|
||||
rb_cThread = rb_define_class("Thread", rb_cObject);
|
||||
rb_undef_alloc_func(rb_cThread);
|
||||
|
||||
|
|
Loading…
Reference in a new issue