=encoding euc-jp =head1 NAME =begin original threads::shared - Perl extension for sharing data structures between threads =end original threads::shared - スレッド間でデータ構造を共有するための Perl エクステンション =head1 VERSION =begin original This document describes threads::shared version 1.29 =end original このドキュメントは threads::shared バージョン 1.29 を記述しています。 =head1 SYNOPSIS use threads; use threads::shared; my $var :shared; my %hsh :shared; my @ary :shared; my ($scalar, @array, %hash); share($scalar); share(@array); share(%hash); $var = $scalar_value; $var = $shared_ref_value; $var = shared_clone($non_shared_ref_value); $var = shared_clone({'foo' => [qw/foo bar baz/]}); $hsh{'foo'} = $scalar_value; $hsh{'bar'} = $shared_ref_value; $hsh{'baz'} = shared_clone($non_shared_ref_value); $hsh{'quz'} = shared_clone([1..3]); $ary[0] = $scalar_value; $ary[1] = $shared_ref_value; $ary[2] = shared_clone($non_shared_ref_value); $ary[3] = shared_clone([ {}, [] ]); { lock(%hash); ... } cond_wait($scalar); cond_timedwait($scalar, time() + 30); cond_broadcast(@array); cond_signal(%hash); my $lockvar :shared; # condition var != lock var cond_wait($var, $lockvar); cond_timedwait($var, time()+30, $lockvar); =head1 DESCRIPTION =begin original By default, variables are private to each thread, and each newly created thread gets a private copy of each existing variable. This module allows you to share variables across different threads (and pseudo-forks on Win32). It is used together with the L module. =end original デフォルトにおいて、変数は各スレッドに対しプライベートで、新たに生成された スレッドはすでに存在している各変数のプライベートなコピーを得ます。 このモジュールは、異なるスレッド(と Win32 上の擬似 fork)間で変数を 共有することを可能にします。 L モジュールと共に使います。 =begin original This module supports the sharing of the following data types only: scalars and scalar refs, arrays and array refs, and hashes and hash refs. =end original このモジュールは以下のデータ型の共有にのみ対応しています: スカラと スカラリファレンス、配列と配列リファレンス、ハッシュとハッシュリファレンス。 =head1 EXPORT (エクスポート) =begin original The following functions are exported by this module: C, C, C, C, C, C and C =end original いかの関数がこのモジュールによってエクスポートされます: C, C, C, C, C, C, C =begin original Note that if this module is imported when L has not yet been loaded, then these functions all become no-ops. This makes it possible to write modules that will work in both threaded and non-threaded environments. =end original まだ L がロードされていない段階でこのモジュールをインポートすると、 その機能は全て無効になることに注意してください。 これによりスレッド・非スレッド環境の両方で動作するモジュールを 書くことができます。 =head1 FUNCTIONS (関数) =over 4 =item share VARIABLE =begin original C takes a variable and marks it as shared: =end original C は値を引数に取り、それを共有化されたものとしてマークします: my ($scalar, @array, %hash); share($scalar); share(@array); share(%hash); =begin original C will return the shared rvalue, but always as a reference. =end original C は共有された右辺値を返しますが、常にリファレンスとして返します。 =begin original Variables can also be marked as shared at compile time by using the C<:shared> attribute: =end original C<:shared> 属性を使うことで、ある変数をコンパイル時に共有化されたものとして マークすることもできます: my ($var, %hash, @array) :shared; =begin original Shared variables can only store scalars, refs of shared variables, or refs of shared data (discussed in next section): =end original 共有変数はスカラ、共有変数のリファレンス、共有されたデータの リファレンスのみを保管できます (次の節で議論します): my ($var, %hash, @array) :shared; my $bork; # Storing scalars $var = 1; $hash{'foo'} = 'bar'; $array[0] = 1.5; # Storing shared refs $var = \%hash; $hash{'ary'} = \@array; $array[1] = \$var; # The following are errors: # $var = \$bork; # ref of non-shared variable # $hash{'bork'} = []; # non-shared array ref # push(@array, { 'x' => 1 }); # non-shared hash ref =item shared_clone REF =begin original C takes a reference, and returns a shared version of its argument, performing a deep copy on any non-shared elements. Any shared elements in the argument are used as is (i.e., they are not cloned). =end original C はリファレンスを取って、非共有要素のディープコピーを することによって、その引数の共有バージョンを返します。 引数の中の共有要素はそのまま使われます (つまりクローンされません)。 my $cpy = shared_clone({'foo' => [qw/foo bar baz/]}); =begin original Object status (i.e., the class an object is blessed into) is also cloned. =end original オブジェクト状態 (つまりオブジェクトが bless されているクラス) も クローンされます。 my $obj = {'foo' => [qw/foo bar baz/]}; bless($obj, 'Foo'); my $cpy = shared_clone($obj); print(ref($cpy), "\n"); # Outputs 'Foo' =begin original For cloning empty array or hash refs, the following may also be used: =end original 空配列やハッシュリファレンスのクローンには、以下のものも使えます: $var = &share([]); # Same as $var = shared_clone([]); $var = &share({}); # Same as $var = shared_clone({}); =item is_shared VARIABLE =begin original C checks if the specified variable is shared or not. If shared, returns the variable's internal ID (similar to L). Otherwise, returns C. =end original C は、指定された変数が共有されているかどうかをチェックします。 共有されていれば、(L と同様に) 変数の 内部 ID を返します。 そうでなければ、C を返します。 if (is_shared($var)) { print("\$var is shared\n"); } else { print("\$var is not shared\n"); } =begin original When used on an element of an array or hash, C checks if the specified element belongs to a shared array or hash. (It does not check the contents of that element.) =end original 配列やハッシュの要素に使われた場合、C は指定された要素が 共有配列またはハッシュに従っているかどうかをチェックします。 (要素の中身はチェックしません。) my %hash :shared; if (is_shared(%hash)) { print("\%hash is shared\n"); } $hash{'elem'} = 1; if (is_shared($hash{'elem'})) { print("\$hash{'elem'} is in a shared hash\n"); } =item lock VARIABLE =begin original C places a B lock on a variable until the lock goes out of scope. If the variable is locked by another thread, the C call will block until it's available. Multiple calls to C by the same thread from within dynamically nested scopes are safe -- the variable will remain locked until the outermost lock on the variable goes out of scope. =end original C はスコープから外れるまで変数を B<助言> ロックします。 もし他のスレッドによってその変数がロックされているなら、ロックが 可能になるまで C の呼び出しはブロックされます。 動的にネストしたスコープの中から同じスレッドによって複数回 C を 呼び出しても安全です -- 最も外側のロックがスコープから抜けるまでその変数は ロックされ続けます。 =begin original C follows references exactly I level: =end original C はリファレンスを正確に I<1> レベル辿ります: my %hash :shared; my $ref = \%hash; lock($ref); # This is equivalent to lock(%hash) =begin original Note that you cannot explicitly unlock a variable; you can only wait for the lock to go out of scope. This is most easily accomplished by locking the variable inside a block. =end original 明示的に変数を unlock することはできないことに注意してください; ロックがスコープを抜けるのを待つしかありません。 これはブロックの内側で変数をロックすることで最も簡単に達成できます。 my $var :shared; { lock($var); # $var is locked from here to the end of the block ... } # $var is now unlocked =begin original As locks are advisory, they do not prevent data access or modification by another thread that does not itself attempt to obtain a lock on the variable. =end original ロックは助言なので、自分自身で変数のロックを得ようとしない他のスレッドによる データアクセスや変更を防げません。 =begin original You cannot lock the individual elements of a container variable: =end original コンテナ変数の個々の要素のロックはできません: my %hash :shared; $hash{'foo'} = 'bar'; #lock($hash{'foo'}); # Error lock(%hash); # Works =begin original If you need more fine-grained control over shared variable access, see L. =end original もし共有変数へのアクセスについてより精度の高い制御を望むなら、 L を参照してください。 =item cond_wait VARIABLE =item cond_wait CONDVAR, LOCKVAR =begin original The C function takes a B variable as a parameter, unlocks the variable, and blocks until another thread does a C or C for that same locked variable. The variable that C blocked on is relocked after the C is satisfied. If there are multiple threads Cing on the same variable, all but one will re-block waiting to reacquire the lock on the variable. (So if you're only using C for synchronisation, give up the lock as soon as possible). The two actions of unlocking the variable and entering the blocked wait state are atomic, the two actions of exiting from the blocked wait state and re-locking the variable are not. =end original C 関数は B<ロックされた> 変数を引数に取り、その変数のロックを 解除します。 そして他のスレッドがその同じロックされていた変数に向けて C か C するまで、ブロック(待機)します。 C がブロックする変数は、C が完了した後、再度 ロックされます。 もし複数のスレッドが同じ変数に対して C しているなら、 一つを除いて全てのスレッドがロックを獲得するまで待機するために再度 ブロックします (よって同期のために C を使うだけなら、可能な限り 早くロックを解除してください)。 変数のロック解除と、ブロックされて待ち状態に入るという二つの動作は アトミックです。 待ち状態から抜けることと、変数の再ロックという二つの動作は、 アトミックではありません。 =begin original In its second form, C takes a shared, B variable followed by a shared, B variable. The second variable is unlocked and thread execution suspended until another thread signals the first variable. =end original 第二の書式では、C は B<ロックされていない> 共有変数をとり、 その後ろに B<ロック> された共有変数がきます。 この二番目の変数はロックが解除され、そして他のスレッドが一番目の変数に シグナルを送るまで、そのスレッドの実行は停止します。 =begin original It is important to note that the variable can be notified even if no thread C or C on the variable. It is therefore important to check the value of the variable and go back to waiting if the requirement is not fulfilled. For example, to pause until a shared counter drops to zero: =end original どのスレッドも、変数に対し C や C をしなくても、 その変数は notify されうるということに注意することが重要です。 それゆえ、変数の値のチェック及び、要求が満たされない場合に待ち状態へ 戻ることが重要です。 例えば、共有カウンタが 0 になるまで停止するには: { lock($counter); cond_wait($counter) until $counter == 0; } =item cond_timedwait VARIABLE, ABS_TIMEOUT =item cond_timedwait CONDVAR, ABS_TIMEOUT, LOCKVAR =begin original In its two-argument form, C takes a B variable and an absolute timeout as parameters, unlocks the variable, and blocks until the timeout is reached or another thread signals the variable. A false value is returned if the timeout is reached, and a true value otherwise. In either case, the variable is re-locked upon return. =end original 二つの引数をとる形式では、C は B<ロックされた> 変数と 絶対的なタイムアウト時間を引数にとります。 変数はロック解除され、タイムアウト時間に達するか、他のスレッドが変数に シグナルを送るかするまでブロックされます。 タイムアウトになると偽の値が返されます。 そうでなければ真の値が返されます。 どちらの場合でも戻りの際に変数は再ロックされます。 =begin original Like C, this function may take a shared, B variable as an additional parameter; in this case the first parameter is an B condition variable protected by a distinct lock variable. =end original C 同様、この関数は B<ロックされた> 共有変数を追加の パラメータとしてとれます; この場合、最初のパラメータは B<ロックされていない> 条件変数であり、これと区別されるロック変数によって 守られます。 =begin original Again like C, waking up and reacquiring the lock are not atomic, and you should always check your desired condition after this function returns. Since the timeout is an absolute value, however, it does not have to be recalculated with each pass: =end original さらに C 同様、覚醒とロックの再獲得はアトミックではありません。 この関数が戻った後、あなたが望んだ状態になっているかどうか常に チェックするべきです。 しかし、タイムアウトは絶対的な値なので、パスごとに再計算させるべきでは ありません: lock($var); my $abs = time() + 15; until ($ok = desired_condition($var)) { last if !cond_timedwait($var, $abs); } # we got it if $ok, otherwise we timed out! =item cond_signal VARIABLE =begin original The C function takes a B variable as a parameter and unblocks one thread that's Cing on that variable. If more than one thread is blocked in a C on that variable, only one (and which one is indeterminate) will be unblocked. =end original C 関数は B<ロックされた> 変数を引数にとり、その変数に対して C している一つのスレッドのブロックを解除します。 もし一つ以上のスレッドが C してブロックされているなら、ただ一つの スレッドだけがブロックを解除されます (そしてどの一つかは不確定です)。 =begin original If there are no threads blocked in a C on the variable, the signal is discarded. By always locking before signaling, you can (with care), avoid signaling before another thread has entered cond_wait(). =end original もしどのスレッドもその変数を C していない場合、シグナルは 破棄されます。 常にシグナルの前にロックされるので、他のスレッドが cond_wait() に入る前に シグナルを発するのを(注意深くやれば)回避することが出来ます。 =begin original C will normally generate a warning if you attempt to use it on an unlocked variable. On the rare occasions where doing this may be sensible, you can suppress the warning with: =end original ロックされていない変数に対し C を試みると、通常は警告を 発します。 稀に起こるこの警告がうるさい場合、次の方法で警告を抑制することができます: { no warnings 'threads'; cond_signal($foo); } =item cond_broadcast VARIABLE =begin original The C function works similarly to C. C, though, will unblock B the threads that are blocked in a C on the locked variable, rather than only one. =end original C 関数は C とよく似た働きをします。 しかし C はスレッド一つだけではなく、ロックされた変数に 対して C して待機中の B<全ての> スレッドをブロック解除します。 =back =head1 OBJECTS =begin original L exports a version of L that works on shared objects such that I propagate across threads. =end original L I がスレッドをまたいで伝搬するような 共有オブジェクトで動作するバージョンの L を エクスポートします。 # Create a shared 'Foo' object my $foo :shared = shared_clone({}); bless($foo, 'Foo'); # Create a shared 'Bar' object my $bar :shared = shared_clone({}); bless($bar, 'Bar'); # Put 'bar' inside 'foo' $foo->{'bar'} = $bar; # Rebless the objects via a thread threads->create(sub { # Rebless the outer object bless($foo, 'Yin'); # Cannot directly rebless the inner object #bless($foo->{'bar'}, 'Yang'); # Retrieve and rebless the inner object my $obj = $foo->{'bar'}; bless($obj, 'Yang'); $foo->{'bar'} = $obj; })->join(); print(ref($foo), "\n"); # Prints 'Yin' print(ref($foo->{'bar'}), "\n"); # Prints 'Yang' print(ref($bar), "\n"); # Also prints 'Yang' =head1 NOTES (注意) =begin original L is designed to disable itself silently if threads are not available. This allows you to write modules and packages that can be used in both threaded and non-threaded applications. =end original threads が利用できない場合、L は黙って利用不可になるよう 設計されています。 これにより、スレッドと非スレッドの両方のアプリケーションで使えるモジュールと パッケージを書けます。 =begin original If you want access to threads, you must C before you C. L will emit a warning if you use it after L. =end original threads にアクセスしようとするなら、C する前に C しなければなりません。 L の後に L を use しようとすれば、警告が 発せられます。 =head1 BUGS AND LIMITATIONS (バグと制限) =begin original When C is used on arrays, hashes, array refs or hash refs, any data they contain will be lost. =end original C が配列、ハッシュ、配列リファレンス、ハッシュリファレンスで 使われると、含まれるあらゆるデータは失われます。 my @arr = qw(foo bar baz); share(@arr); # @arr is now empty (i.e., == ()); # Create a 'foo' object my $foo = { 'data' => 99 }; bless($foo, 'foo'); # Share the object share($foo); # Contents are now wiped out print("ERROR: \$foo is empty\n") if (! exists($foo->{'data'})); =begin original Therefore, populate such variables B declaring them as shared. (Scalar and scalar refs are not affected by this problem.) =end original 従って、このような変数は、共有すると宣言した B<後に> 設定してください。 (スカラとスカラリファレンスはこの問題の影響を受けません。) =begin original It is often not wise to share an object unless the class itself has been written to support sharing. For example, an object's destructor may get called multiple times, once for each thread's scope exit. Another danger is that the contents of hash-based objects will be lost due to the above mentioned limitation. See F (in the CPAN distribution of this module) for how to create a class that supports object sharing. =end original クラス自身が共有に対応するように書かれていないオブジェクトを共有することは たいてい賢明なこととは言えません。 例えば、各スレッドのスコープから外れる毎に、あるオブジェクトの デストラクタが複数回呼び出されるかも知れません。 もう一つの危険性は、ハッシュベースのオブジェクトの内容が、上述した 制限のために失われてしまうことです。 オブジェクト共有に対応したクラスの作り方については、(このモジュールの CPAN 配布に含まれている F を参照してください。 =begin original Does not support C on arrays! =end original 配列に対する C はサポートしていません! =begin original Taking references to the elements of shared arrays and hashes does not autovivify the elements, and neither does slicing a shared array/hash over non-existent indices/keys autovivify the elements. =end original 共有化された配列とハッシュの要素へのリファレンスをとっても 自動有効化しません。 また、共有配列/ハッシュで存在しないインデックスやキーにスライスしても、 その要素は自動有効化しません。 =begin original C allows you to C<< share($hashref->{key}) >> and C<< share($arrayref->[idx]) >> without giving any error message. But the C<< $hashref->{key} >> or C<< $arrayref->[idx] >> is B shared, causing the error "lock can only be used on shared values" to occur when you attempt to C<< lock($hasref->{key}) >> or C<< lock($arrayref->[idx]) >> in another thread. =end original C<< share($hashref->{key}) >> や C<< share($arrayref->[idx]) >> しても、 C はエラーメッセージを出しません。 しかし、C<< $hashref->{key} >> や C<< $arrayref->[idx] >> は共有 B<されません>; 他のスレッドで C<< lock($hashref->{key}) >> や C<< lock($arrayref->[idx]) >> しようとすれば "locking can only be used on shared values" (ロックは共有変数に対してのみ 使用できます) というエラーが発生します。 =begin original Using L) is unreliable for testing whether or not two shared references are equivalent (e.g., when testing for circular references). Use L, instead: =end original L) の使用は、二つの共有リファレンスが 等価かどうかをテストする (例えば循環参照をテストする) には信頼性が ありません。 代わりに L を使ってください: use threads; use threads::shared; use Scalar::Util qw(refaddr); # If ref is shared, use threads::shared's internal ID. # Otherwise, use refaddr(). my $addr1 = is_shared($ref1) || refaddr($ref1); my $addr2 = is_shared($ref2) || refaddr($ref2); if ($addr1 == $addr2) { # The refs are equivalent } =begin original L does not work properly on shared references embedded in shared structures. For example: =end original L は共有構造体に組み込まれた共有リファレンスには 正しく動作しません。 例えば: my %foo :shared; $foo{'bar'} = shared_clone({'a'=>'x', 'b'=>'y', 'c'=>'z'}); while (my ($key, $val) = each(%{$foo{'bar'}})) { ... } =begin original Either of the following will work instead: =end original しかし以下のどちらかは動作します: my $ref = $foo{'bar'}; while (my ($key, $val) = each(%{$ref})) { ... } foreach my $key (keys(%{$foo{'bar'}})) { my $val = $foo{'bar'}{$key}; ... } =begin original View existing bug reports at, and submit any new bugs, problems, patches, etc. to: L =end original 既に報告されているバグの閲覧や、新しいバグ、問題、パッチなどの投稿先: L =head1 SEE ALSO =begin original L Discussion Forum on CPAN: L =end original CPAN の L ディスカッションフォーラム: L =begin original Annotated POD for L: L =end original L の注釈付き POD: L =begin original Source repository: L =end original ソースレポジトリ: L L, L =begin original L and L =end original L と L =begin original Perl threads mailing list: L =end original Perl threads メーリングリスト: L =head1 AUTHOR Artur Bergman Esky AT crucially DOT netE Documentation borrowed from the old Thread.pm. CPAN version produced by Jerry D. Hedden Ejdhedden AT cpan DOT orgE. =head1 LICENSE threads::shared is released under the same license as Perl. =cut =begin meta Update: SHIRAKATA Kentaro (1.14-) Status: completed =end meta