Repository URL to install this package:
Version:
2.2.2-1 ▾
|
U:RDoc::NormalClass[iI"Thread:ET@I"Object;To:RDoc::Markup::Document:@parts[o;;[ : @fileI"prelude.rb;T:0@omit_headings_from_table_of_contents_below0o;;[So:RDoc::Markup::Paragraph;[I"LThreads are the Ruby implementation for a concurrent programming model.;To:RDoc::Markup::BlankLine o;;[I"GPrograms that require multiple threads of execution are a perfect ;TI"'candidate for Ruby's Thread class.;T@o;;[I"MFor example, we can create a new thread separate from the main thread's ;TI"execution using ::new.;T@o:RDoc::Markup::Verbatim;[I"4thr = Thread.new { puts "Whats the big deal" } ;T:@format0o;;[I"JThen we are able to pause the execution of the main thread and allow ;TI"+our new thread to finish, using #join:;T@o; ;[I"'thr.join #=> "Whats the big deal" ;T;0o;;[I"MIf we don't call +thr.join+ before the main thread terminates, then all ;TI"2other threads including +thr+ will be killed.;T@o;;[I"JAlternatively, you can use an array for handling multiple threads at ;TI")once, like in the following example:;T@o; ;[I"threads = [] ;TI"9threads << Thread.new { puts "Whats the big deal" } ;TI"Cthreads << Thread.new { 3.times { puts "Threads are fun!" } } ;T;0o;;[I"AAfter creating a few threads we wait for them all to finish ;TI"consecutively.;T@o; ;[I"%threads.each { |thr| thr.join } ;T;0S:RDoc::Markup::Heading: leveli: textI"Thread initialization;T@o;;[I"GIn order to create new threads, Ruby provides ::new, ::start, and ;TI"L::fork. A block must be provided with each of these methods, otherwise ;TI""a ThreadError will be raised.;T@o;;[I"HWhen subclassing the Thread class, the +initialize+ method of your ;TI"Ksubclass will be ignored by ::start and ::fork. Otherwise, be sure to ;TI",call super in your +initialize+ method.;T@S;;i;I"Thread termination;T@o;;[I"IFor terminating threads, Ruby provides a variety of ways to do this.;T@o;;[I">The class method ::kill, is meant to exit a given thread:;T@o; ;[I"thr = Thread.new { ... } ;TI",Thread.kill(thr) # sends exit() to thr ;T;0o;;[I"IAlternatively, you can use the instance method #exit, or any of its ;TI"!aliases #kill or #terminate.;T@o; ;[I"thr.exit ;T;0S;;i;I"Thread status;T@o;;[I"LRuby provides a few instance methods for querying the state of a given ;TI"Hthread. To get a string with the current thread's state use #status;T@o; ;[ I" thr = Thread.new { sleep } ;TI"thr.status # => "sleep" ;TI"thr.exit ;TI"thr.status # => false ;T;0o;;[I"LYou can also use #alive? to tell if the thread is running or sleeping, ;TI"2and #stop? if the thread is dead or sleeping.;T@S;;i;I"Thread variables and scope;T@o;;[I"JSince threads are created with blocks, the same rules apply to other ;TI"MRuby blocks for variable scope. Any local variables created within this ;TI".block are accessible to only this thread.;T@S;;i ;I"!Fiber-local vs. Thread-local;T@o;;[I"IEach fiber has its own bucket for Thread#[] storage. When you set a ;TI"Lnew fiber-local it is only accessible within this Fiber. To illustrate:;T@o; ;[I"Thread.new { ;TI"$ Thread.current[:foo] = "bar" ;TI" Fiber.new { ;TI") p Thread.current[:foo] # => nil ;TI" }.resume ;TI"}.join ;T;0o;;[I"JThis example uses #[] for getting and #[]= for setting fiber-locals, ;TI"Ayou can also use #keys to list the fiber-locals for a given ;TI"7thread and #key? to check if a fiber-local exists.;T@o;;[I"KWhen it comes to thread-locals, they are accessible within the entire ;TI"6scope of the thread. Given the following example:;T@o; ;[I"Thread.new{ ;TI"3 Thread.current.thread_variable_set(:foo, 1) ;TI"9 p Thread.current.thread_variable_get(:foo) # => 1 ;TI" Fiber.new{ ;TI"5 Thread.current.thread_variable_set(:foo, 2) ;TI"; p Thread.current.thread_variable_get(:foo) # => 2 ;TI" }.resume ;TI"; p Thread.current.thread_variable_get(:foo) # => 2 ;TI"}.join ;T;0o;;[I"JYou can see that the thread-local +:foo+ carried over into the fiber ;TI"5and was changed to +2+ by the end of the thread.;T@o;;[I"BThis example makes use of #thread_variable_set to create new ;TI"?thread-locals, and #thread_variable_get to reference them.;T@o;;[I"DThere is also #thread_variables to list all thread-locals, and ;TI"?#thread_variable? to check if a given thread-local exists.;T@S;;i;I"Exception handling;T@o;;[I"IAny thread can raise an exception using the #raise instance method, ;TI".which operates similarly to Kernel#raise.;T@o;;[I"JHowever, it's important to note that an exception that occurs in any ;TI"Hthread except the main thread depends on #abort_on_exception. This ;TI"Moption is +false+ by default, meaning that any unhandled exception will ;TI"Kcause the thread to terminate silently when waited on by either #join ;TI"Kor #value. You can change this default by either #abort_on_exception= ;TI"(+true+ or setting $DEBUG to +true+.;T@o;;[I"KWith the addition of the class method ::handle_interrupt, you can now ;TI"3handle exceptions asynchronously with threads.;T@S;;i;I"Scheduling;T@o;;[I"LRuby provides a few ways to support scheduling threads in your program.;T@o;;[I"KThe first way is by using the class method ::stop, to put the current ;TI"Jrunning thread to sleep and schedule the execution of another thread.;T@o;;[I"IOnce a thread is asleep, you can use the instance method #wakeup to ;TI"1mark your thread as eligible for scheduling.;T@o;;[I"JYou can also try ::pass, which attempts to pass execution to another ;TI"Lthread but is dependent on the OS whether a running thread will switch ;TI"Lor not. The same goes for #priority, which lets you hint to the thread ;TI"Fscheduler which threads you want to take precedence when passing ;TI"Kexecution. This method is also dependent on the OS and may be ignored ;TI"on some platforms.;T; I" vm.c;T; 0; 0; 0[ [ [ [[I" class;T[[:public[[I" DEBUG;TI" thread.c;T[I"DEBUG=;T@Ì[I"abort_on_exception;T@Ì[I"abort_on_exception=;T@Ì[I"current;T@Ì[I"exclusive;FI"prelude.rb;T[I" exit;T@Ì[I" fork;T@Ì[I"handle_interrupt;T@Ì[I" kill;T@Ì[I" list;T@Ì[I" main;T@Ì[I"new;T@Ì[I" pass;T@Ì[I"pending_interrupt?;T@Ì[I" start;T@Ì[I" stop;T@Ì[:protected[ [:private[ [I" instance;T[[;[$[I"[];T@Ì[I"[]=;T@Ì[I"abort_on_exception;T@Ì[I"abort_on_exception=;T@Ì[I"add_trace_func;TI"vm_trace.c;T[I"alive?;T@Ì[I"backtrace;T@Ì[I"backtrace_locations;T@Ì[I" exit;T@Ì[I" group;T@Ì[I"inspect;T@Ì[I" join;T@Ì[I" key?;T@Ì[I" keys;T@Ì[I" kill;T@Ì[I"pending_interrupt?;T@Ì[I" priority;T@Ì[I"priority=;T@Ì[I" raise;T@Ì[I"run;T@Ì[I"safe_level;T@Ì[I"set_trace_func;T@[I"status;T@Ì[I" stop?;T@Ì[I"terminate;T@Ì[I"thread_variable?;T@Ì[I"thread_variable_get;T@Ì[I"thread_variable_set;T@Ì[I"thread_variables;T@Ì[I" value;T@Ì[I"wakeup;T@Ì[;[ [;[ [ [U:RDoc::Context::Section[i 0o;;[ ; 0; 0[ @ I" thread.c;T@ÀI"vm_trace.c;T@BcRDoc::TopLevel