HEX
Server: Apache
System: Linux s198.coreserver.jp 5.15.0-151-generic #161-Ubuntu SMP Tue Jul 22 14:25:40 UTC 2025 x86_64
User: nagasaki (10062)
PHP: 7.1.33
Disabled: NONE
Upload Files
File: //usr/local/rvm/gems/ruby-2.7.4/doc/concurrent-ruby-1.1.9/ri/Concurrent/Async/cdesc-Async.ri
U:RDoc::NormalModule[iI"
Async:ETI"Concurrent::Async;T0o:RDoc::Markup::Document:@parts[o;;[co:RDoc::Markup::Paragraph;[	I"KA mixin module that provides simple asynchronous behavior to a class, ;TI"?turning it into a simple actor. Loosely based on Erlang's ;TI"N[gen_server](http://www.erlang.org/doc/man/gen_server.html), but without ;TI"supervision or linking.;To:RDoc::Markup::BlankLineo;	;[I"HA more feature-rich {Concurrent::Actor} is also available when the ;TI"-capabilities of `Async` are too limited.;T@o;	;[I"```cucumber ;TI"
Feature:;To:RDoc::Markup::Verbatim;[I")As a stateful, plain old Ruby class
;TI"(I want safe, asynchronous behavior
;TI"<So my long-running methods don't block the main thread
;T:@format0o;	;[I"```;T@o;	;[
I"IThe `Async` module is a way to mix simple yet powerful asynchronous ;TI"Ocapabilities into any plain old Ruby object or class, turning each object ;TI"Qinto a simple Actor. Method calls are processed on a background thread. The ;TI"Lcaller is free to perform other actions while processing occurs in the ;TI"background.;T@o;	;[	I"MMethod calls to the asynchronous object are made via two proxy methods: ;TI"Q`async` (alias `cast`) and `await` (alias `call`). These proxy methods post ;TI"Mthe method call to the object's background thread and return a "future" ;TI"Awhich will eventually contain the result of the method call.;T@o;	;[
I"NThis behavior is loosely patterned after Erlang's `gen_server` behavior. ;TI"KWhen an Erlang module implements the `gen_server` behavior it becomes ;TI"Linherently asynchronous. The `start` or `start_link` function spawns a ;TI"Oprocess (similar to a thread but much more lightweight and efficient) and ;TI"Nreturns the ID of the process. Using the process ID, other processes can ;TI"Qsend messages to the `gen_server` via the `cast` and `call` methods. Unlike ;TI"OErlang's `gen_server`, however, `Async` classes do not support linking or ;TI"supervision trees.;T@o;	;[I"## Basic Usage;T@o;	;[	I"TWhen this module is mixed into a class, objects of the class become inherently ;TI"Oasynchronous. Each object gets its own background thread on which to post ;TI"Nasynchronous method calls. Asynchronous method calls are executed in the ;TI"=background one at a time in the order they are received.;T@o;	;[I"STo create an asynchronous class, simply mix in the `Concurrent::Async` module:;T@o;	;[I"	``` ;TI"class Hello;To;;[
I"include Concurrent::Async
;TI"
;TI"def hello(name)
;TI"  "Hello, #{name}!"
;TI"	end
;T;0o;	;[I"	end ;TI"```;T@o;	;[I"MMixing this module into a class provides each object two proxy methods: ;TI"L`async` and `await`. These methods are thread safe with respect to the ;TI"Denclosing object. The former proxy allows methods to be called ;TI"Qasynchronously by posting to the object's internal thread. The latter proxy ;TI"Pallows a method to be called synchronously but does so safely with respect ;TI"Pto any pending asynchronous method calls and ensures proper ordering. Both ;TI"Omethods return a {Concurrent::IVar} which can be inspected for the result ;TI"Mof the proxied method call. Calling a method with `async` will return a ;TI"H`:pending` `IVar` whereas `await` will return a `:complete` `IVar`.;T@o;	;[I"	``` ;TI"class Echo;To;;[
I"include Concurrent::Async
;TI"
;TI"def echo(msg)
;TI"  print "#{msg}\n"
;TI"	end
;T;0o;	;[I"end;T@o;	;[I"horn = Echo.new ;TI":horn.echo('zero')      # synchronous, not thread-safe;To;;[I"5# returns the actual return value of the method
;T;0o;	;[I"Ehorn.async.echo('one') # asynchronous, non-blocking, thread-safe;To;;[I"-# returns an IVar in the :pending state
;T;0o;	;[I"@horn.await.echo('two') # synchronous, blocking, thread-safe;To;;[I".# returns an IVar in the :complete state
;T;0o;	;[I"```;T@o;	;[I"## Let It Fail;T@o;	;[
I"PThe `async` and `await` proxy methods have built-in error protection based ;TI"Qon Erlang's famous "let it fail" philosophy. Instance methods should not be ;TI"Oprogrammed defensively. When an exception is raised by a delegated method ;TI"Rthe proxy will rescue the exception, expose it to the caller as the `reason` ;TI"Iattribute of the returned future, then process the next method call.;T@o;	;[I""## Calling Methods Internally;T@o;	;[I"MExternal method calls should *always* use the `async` and `await` proxy ;TI"Mmethods. When one method calls another method, the `async` proxy should ;TI"Ararely be used and the `await` proxy should *never* be used.;T@o;	;[	I"MWhen an object calls one of its own methods using the `await` proxy the ;TI"Nsecond call will be enqueued *behind* the currently running method call. ;TI"OAny attempt to wait on the result will fail as the second call will never ;TI"0run until after the current call completes.;T@o;	;[I"LCalling a method using the `await` proxy from within a method that was ;TI"Kitself called using `async` or `await` will irreversibly deadlock the ;TI"$object. Do *not* do this, ever.;T@o;	;[I"2## Instance Variables and Attribute Accessors;T@o;	;[	I"SInstance variables do not need to be thread-safe so long as they are private. ;TI"PAsynchronous method calls are processed in the order they are received and ;TI"Pare processed one at a time. Therefore private instance variables can only ;TI"Ibe accessed by one thread at a time. This is inherently thread-safe.;T@o;	;[
I"QWhen using private instance variables within asynchronous methods, the best ;TI"Rpractice is to read the instance variable into a local variable at the start ;TI"Qof the method then update the instance variable at the *end* of the method. ;TI"RThis way, should an exception be raised during method execution the internal ;TI"4state of the object will not have been changed.;T@o;	;[I"### Reader Attributes;T@o;	;[
I"QThe use of `attr_reader` is discouraged. Internal state exposed externally, ;TI"Kwhen necessary, should be done through accessor methods. The instance ;TI"Ovariables exposed by these methods *must* be thread-safe, or they must be ;TI"Rcalled using the `async` and `await` proxy methods. These two approaches are ;TI"subtly different.;T@o;	;[	I"PWhen internal state is accessed via the `async` and `await` proxy methods, ;TI"Othe returned value represents the object's state *at the time the call is ;TI"Qprocessed*, which may *not* be the state of the object at the time the call ;TI"
is made.;T@o;	;[I"PTo get the state *at the current* time, irrespective of an enqueued method ;TI"Ocalls, a reader method must be called directly. This is inherently unsafe ;TI"Nunless the instance variable is itself thread-safe, preferably using one ;TI"Mof the thread-safe classes within this library. Because the thread-safe ;TI"Qclasses within this library are internally-locking or non-locking, they can ;TI"Obe safely used from within asynchronous methods without causing deadlocks.;T@o;	;[I"QGenerally speaking, the best practice is to *not* expose internal state via ;TI"Rreader methods. The best practice is to simply use the method's return value.;T@o;	;[I"### Writer Attributes;T@o;	;[I"PWriter attributes should never be used with asynchronous classes. Changing ;TI"Sthe state externally, even when done in the thread-safe way, is not logically ;TI"Tconsistent. Changes to state need to be timed with respect to all asynchronous ;TI"Smethod calls which my be in-process or enqueued. The only safe practice is to ;TI"Spass all necessary data to each method as arguments and let the method update ;TI"%the internal state as necessary.;T@o;	;[I"/## Class Constants, Variables, and Methods;T@o;	;[I"### Class Constants;T@o;	;[I"QClass constants do not need to be thread-safe. Since they are read-only and ;TI"Gimmutable they may be safely read both externally and from within ;TI"asynchronous methods.;T@o;	;[I"### Class Variables;T@o;	;[I"PClass variables should be avoided. Class variables represent shared state. ;TI"NShared state is anathema to concurrency. Should there be a need to share ;TI"Hstate using class variables they *must* be thread-safe, preferably ;TI"Lusing the thread-safe classes within this library. When updating class ;TI"Svariables, never assign a new value/object to the variable itself. Assignment ;TI"Ois not thread-safe in Ruby. Instead, use the thread-safe update functions ;TI"0of the variable itself to change the value.;T@o;	;[I"NThe best practice is to *never* use class variables with `Async` classes.;T@o;	;[I"### Class Methods;T@o;	;[I"QClass methods which are pure functions are safe. Class methods which modify ;TI"Iclass variables should be avoided, for all the reasons listed above.;T@o;	;[I"6## An Important Note About Thread Safe Guarantees;T@o;	;[I"N> Thread safe guarantees can only be made when asynchronous method calls ;TI"L> are not mixed with direct method calls. Use only direct method calls ;TI"H> when the object is used exclusively on a single thread. Use only ;TI"O> `async` and `await` when the object is shared between threads. Once you ;TI"Q> call a method using `async` or `await`, you should no longer call methods ;TI"P> directly on the object. Use `async` and `await` exclusively from then on.;T@o;	;[I"
@example;T@o;;[I"class Echo
;TI"!  include Concurrent::Async
;TI"
;TI"  def echo(msg)
;TI"    print "#{msg}\n"
;TI"  end
;TI"	end
;TI"
;TI"horn = Echo.new
;TI";horn.echo('zero')      # synchronous, not thread-safe
;TI"L                       # returns the actual return value of the method
;TI"
;TI"Fhorn.async.echo('one') # asynchronous, non-blocking, thread-safe
;TI"D                       # returns an IVar in the :pending state
;TI"
;TI"Ahorn.await.echo('two') # synchronous, blocking, thread-safe
;TI"E                       # returns an IVar in the :complete state
;T;0o;	;[	I"@see Concurrent::Actor ;TI"O@see https://en.wikipedia.org/wiki/Actor_model "Actor Model" at Wikipedia ;TI"J@see http://www.erlang.org/doc/man/gen_server.html Erlang gen_server ;TI"L@see http://c2.com/cgi/wiki?LetItCrash "Let It Crash" at http://c2.com/;T:
@fileI",lib/concurrent-ruby/concurrent/async.rb;T:0@omit_headings_from_table_of_contents_below0;
0;0[[[[[I"
class;T[[:public[[I"
included;TI",lib/concurrent-ruby/concurrent/async.rb;T[I"validate_argc;T@([:protected[[:private[[I"
instance;T[[;[
[I"
async;T@([I"
await;T@([I"	call;T@([I"	cast;T@([I"init_synchronization;T@([;[[;[[[U:RDoc::Context::Section[i0o;;[;
0;0[@I"Concurrent;TcRDoc::NormalModule