1f2ad9d99cdb8af2c91a7c1739269b813d2cb9b2
[p5sagit/p5-mst-13.2.git] / ext / threads / shared / shared.pm
1 package threads::shared;
2
3 use strict;
4 use warnings;
5 use Config;
6 use Scalar::Util qw(weaken);
7 use attributes qw(reftype);
8
9 BEGIN {
10     if($Config{'useithreads'} && $threads::threads) {
11         *share = \&share_enabled;
12         *cond_wait = \&cond_wait_enabled;
13         *cond_signal = \&cond_signal_enabled;
14         *cond_broadcast = \&cond_broadcast_enabled;
15         *unlock = \&unlock_enabled;
16     } else {
17         *share = \&share_disabled;
18         *cond_wait = \&cond_wait_disabled;
19         *cond_signal = \&cond_signal_disabled;
20         *cond_broadcast = \&cond_broadcast_disabled;
21         *unlock = \&unlock_disabled;
22     }
23 }
24
25 require Exporter;
26 require DynaLoader;
27 our @ISA = qw(Exporter DynaLoader);
28
29 our @EXPORT = qw(share cond_wait cond_broadcast cond_signal unlock);
30 our $VERSION = '0.90';
31
32 our %shared;
33
34 sub cond_wait_disabled { return @_ };
35 sub cond_signal_disabled { return @_};
36 sub cond_broadcast_disabled { return @_};
37 sub unlock_disabled { 1 };
38 sub lock_disabled { 1 }
39 sub share_disabled { return @_}
40
41 sub share_enabled (\[$@%]) { # \]     
42     my $value = $_[0];
43     my $ref = reftype($value);
44     if($ref eq 'SCALAR') {
45         my $obj = \threads::shared::sv->new($$value);
46         bless $obj, 'threads::shared::sv';
47         $shared{$$obj} = $value;
48         weaken($shared{$$obj});
49     } elsif($ref eq "ARRAY") {
50         tie @$value, 'threads::shared::av', $value;
51     } elsif($ref eq "HASH") {
52         tie %$value, "threads::shared::hv", $value;
53     } else {
54         die "You cannot share ref of type $_[0]\n";
55     }
56 }
57
58 sub CLONE {
59     return unless($_[0] eq "threads::shared");
60         foreach my $ptr (keys %shared) {
61             if($ptr) {
62                 thrcnt_inc($shared{$ptr},$threads::origthread);
63             }
64         }
65 }
66
67 sub DESTROY {
68     my $self = shift;
69     _thrcnt_dec($$self);
70     delete($shared{$$self});
71 }
72
73 package threads::shared::sv;
74 use base 'threads::shared';
75
76 sub DESTROY {}
77
78 package threads::shared::av;
79 use base 'threads::shared';
80 use Scalar::Util qw(weaken);
81 sub TIEARRAY {
82         my $class = shift;
83         my $value = shift;
84         my $self = bless \threads::shared::av->new($value),'threads::shared::av';
85         $shared{$self->ptr} = $value;
86         weaken($shared{$self->ptr});
87         return $self;
88 }
89
90 package threads::shared::hv;
91 use base 'threads::shared';
92 use Scalar::Util qw(weaken);
93 sub TIEHASH {
94     my $class = shift;
95     my $value = shift;
96     my $self = bless \threads::shared::hv->new($value),'threads::shared::hv';
97     $shared{$self->ptr} = $value;
98     weaken($shared{$self->ptr});
99     return $self;
100 }
101
102 package threads::shared;
103
104 $threads::shared::threads_shared = 1;
105
106 bootstrap threads::shared $VERSION;
107
108 __END__
109
110 =head1 NAME
111
112 threads::shared - Perl extension for sharing data structures between threads
113
114 =head1 SYNOPSIS
115
116   use threads::shared;
117
118   my($foo, @foo, %foo);
119   share($foo);
120   share(@foo);
121   share(%hash);
122   my $bar = share([]);
123   $hash{bar} = share({});
124
125   lock(%hash);
126   unlock(%hash);
127   cond_wait($scalar);
128   cond_broadcast(@array);
129   cond_signal(%hash);
130
131 =head1 DESCRIPTION
132
133 This modules allows you to share() variables. These variables will
134 then be shared across different threads (and pseudoforks on
135 win32). They are used together with the threads module.
136
137 =head1 EXPORT
138
139 C<share>, C<lock>, C<unlock>, C<cond_wait>, C<cond_signal>, C<cond_broadcast>
140
141 =head1 FUNCTIONS
142
143 =over 4
144
145 =item share VARIABLE
146
147 C<share> takes a value and marks it as shared, you can share a scalar, array, hash
148 scalar ref, array ref and hash ref, C<share> will return the shared value.
149
150 C<share> will traverse up references exactly I<one> level.
151 C<share(\$a)> is equivalent to C<share($a)>, while C<share(\\$a)> is not.
152
153 =item lock VARIABLE
154
155 C<lock> places a lock on a variable until the lock goes out of scope.  If
156 the variable is locked by another thread, the C<lock> call will block until
157 it's available. C<lock> is recursive, so multiple calls to C<lock> are
158 safe--the variable will remain locked until the outermost lock on the
159 variable goes out of scope or C<unlock> is called enough times to match 
160 the number of calls to <lock>.
161
162 If a container object, such as a hash or array, is locked, all the elements
163 of that container are not locked. For example, if a thread does a C<lock
164 @a>, any other thread doing a C<lock($a[12])> won't block.
165
166 C<lock> will traverse up references exactly I<one> level.
167 C<lock(\$a)> is equivalent to C<lock($a)>, while C<lock(\\$a)> is not.
168
169
170 =item unlock VARIABLE
171
172 C<unlock> takes a locked shared value and decrements the lock count.
173 If the lock count is zero the variable is unlocked. It is not necessary
174 to call C<unlock> but it can be usefull to reduce lock contention.
175
176 C<unlock> will traverse up references exactly I<one> level.
177 C<unlock(\$a)> is equivalent to C<unlock($a)>, while C<unlock(\\$a)> is not.
178
179 =item cond_wait VARIABLE
180
181 The C<cond_wait> function takes a B<locked> variable as a parameter,
182 unlocks the variable, and blocks until another thread does a C<cond_signal>
183 or C<cond_broadcast> for that same locked variable. The variable that
184 C<cond_wait> blocked on is relocked after the C<cond_wait> is satisfied.
185 If there are multiple threads C<cond_wait>ing on the same variable, all but
186 one will reblock waiting to reaquire the lock on the variable. (So if
187 you're only using C<cond_wait> for synchronization, give up the lock as
188 soon as possible)
189
190 It is important to note that the variable can be notified even if no
191 thread C<cond_signal> or C<cond_broadcast> on the variable. It is therefore
192 important to check the value of the variable and go back to waiting if the
193 requirment is not fullfilled.
194
195 =item cond_signal VARIABLE
196
197 The C<cond_signal> function takes a B<locked> variable as a parameter and
198 unblocks one thread that's C<cond_wait>ing on that variable. If more than
199 one thread is blocked in a C<cond_wait> on that variable, only one (and
200 which one is indeterminate) will be unblocked.
201
202 If there are no threads blocked in a C<cond_wait> on the variable, the
203 signal is discarded.
204
205 =item cond_broadcast VARIABLE
206
207 The C<cond_broadcast> function works similarly to C<cond_signal>.
208 C<cond_broadcast>, though, will unblock B<all> the threads that are blocked
209 in a C<cond_wait> on the locked variable, rather than only one.
210
211
212 =head1 NOTES
213
214 threads::shared is designed is disable itself silently if threads are
215 not available. If you want access to threads, you must C<use threads>
216 before you C<use threads::shared>.  threads will emit a warning if you
217 use it before threads::shared.
218
219 =head1 BUGS
220
221 C<bless> is not supported on shared references, in the current version
222 C<bless> will only bless the thread local reference and the blessing
223 will not propagate to the other threads, this is expected to be implmented
224 in the future.
225
226 Does not support splice on arrays!
227
228 =head1 AUTHOR
229
230 Arthur Bergman E<lt>arthur at contiller.seE<gt>
231
232 threads::shared is released under the same license as Perl
233
234 Documentation borrowed from Thread.pm
235
236 =head1 SEE ALSO
237
238 L<perl> L<threads>
239
240 =cut
241
242
243
244
245