Skip to content

Commit 50b974f

Browse files
author
jdhedden
committed
threads-shared v1.04
1 parent 5bfb361 commit 50b974f

File tree

7 files changed

+231
-10
lines changed

7 files changed

+231
-10
lines changed

Changes

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
Revision history for Perl extension threads::shared.
22

3+
1.04 Thu Oct 12 10:50:46 EDT 2006
4+
- Added example script
5+
- Added POD tests
6+
37
1.03 Fri Sep 15 15:09:26 EDT 2006
4-
- Fix memory leak caused blessed shared objects
8+
- Fix memory leak caused by blessed shared objects
59
- Upgraded ppport.h to Devel::PPPort 3.10
610

711
1.02 Fri Jul 14 08:56:03 EDT 2006

MANIFEST

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ t/disabled.t
1616
t/hv_refs.t
1717
t/hv_simple.t
1818
t/no_share.t
19+
t/pod.t
1920
t/shared_attr.t
2021
t/sv_refs.t
2122
t/sv_simple.t
2223
t/wait.t
24+
examples/class.pl
2325
META.yml Module meta-data (added by MakeMaker)

Makefile.PL

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,23 @@ if (grep { $_ eq 'PERL_CORE=1' } @ARGV) {
6565
# Create Makefile
6666
WriteMakefile(
6767
'NAME' => 'threads::shared',
68-
'AUTHOR' => 'Artur Bergman <sky AT crucially DOT net>',
68+
'AUTHOR' => 'Artur Bergman, Jerry D. Hedden <jdhedden AT cpan DOT org>',
6969
'VERSION_FROM' => 'shared.pm',
7070
'ABSTRACT_FROM' => 'shared.pm',
7171
'PM' => {
7272
'shared.pm' => '$(INST_LIBDIR)/shared.pm',
7373
},
74-
'PREREQ_PM' => {
75-
'threads' => 0,
76-
'XSLoader' => 0,
74+
'PREREQ_PM' => {
75+
'strict' => 0,
76+
'warnings' => 0,
77+
'threads' => 0,
78+
'Config' => 0,
79+
'Carp' => 0,
80+
'XSLoader' => 0,
81+
82+
'Test' => 0,
83+
'Test::More' => 0,
84+
'ExtUtils::testlib' => 0,
7785
},
7886
'INSTALLDIRS' => 'perl',
7987

README

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
threads::shared version 1.03
1+
threads::shared version 1.04
22
============================
33

44
This module needs Perl 5.8.0 or later compiled with USEITHREADS.

examples/class.pl

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
#!/usr/bin/perl
2+
3+
use strict;
4+
use warnings;
5+
6+
use threads;
7+
use threads::shared;
8+
9+
package My::Class; {
10+
use threads::shared qw(share is_shared);
11+
use Scalar::Util qw(reftype blessed);
12+
13+
# Constructor
14+
sub new
15+
{
16+
my $class = shift;
17+
share(my %self);
18+
19+
# Add arguments to object hash
20+
while (my $tag = shift) {
21+
if (!@_) {
22+
require Carp;
23+
Carp::croak("Missing value for '$tag'");
24+
}
25+
$self{$tag} = _make_shared(shift);
26+
}
27+
28+
return (bless(\%self, $class));
29+
}
30+
31+
# Adds fields to a shared object
32+
sub set
33+
{
34+
my ($self, $tag, $value) = @_;
35+
lock($self);
36+
$self->{$tag} = _make_shared($value);
37+
}
38+
39+
# Make a thread-shared version of a complex data structure or object
40+
sub _make_shared
41+
{
42+
my $in = shift;
43+
44+
# If already thread-shared, then just return the input
45+
return ($in) if (is_shared($in));
46+
47+
# Make copies of array, hash and scalar refs
48+
my $out;
49+
if (my $ref_type = reftype($in)) {
50+
# Copy an array ref
51+
if ($ref_type eq 'ARRAY') {
52+
# Make empty shared array ref
53+
$out = &share([]);
54+
# Recursively copy and add contents
55+
foreach my $val (@$in) {
56+
push(@$out, _make_shared($val));
57+
}
58+
}
59+
60+
# Copy a hash ref
61+
elsif ($ref_type eq 'HASH') {
62+
# Make empty shared hash ref
63+
$out = &share({});
64+
# Recursively copy and add contents
65+
foreach my $key (keys(%{$in})) {
66+
$out->{$key} = _make_shared($in->{$key});
67+
}
68+
}
69+
70+
# Copy a scalar ref
71+
elsif ($ref_type eq 'SCALAR') {
72+
$out = \do{ my $scalar = $$in; };
73+
share($out);
74+
}
75+
}
76+
77+
# If copy created above ...
78+
if ($out) {
79+
# Clone READONLY flag
80+
if (Internals::SvREADONLY($in)) {
81+
Internals::SvREADONLY($out, 1);
82+
}
83+
# Make blessed copy, if applicable
84+
if (my $class = blessed($in)) {
85+
bless($out, $class);
86+
}
87+
# Return copy
88+
return ($out);
89+
}
90+
91+
# Just return anything else
92+
# NOTE: This will generate an error if we're thread-sharing,
93+
# and $in is not an ordinary scalar.
94+
return ($in);
95+
}
96+
}
97+
98+
99+
package main;
100+
101+
MAIN:
102+
{
103+
# Create an object containing some complex elements
104+
my $obj = My::Class->new('bar' => { 'ima' => 'hash' },
105+
'baz' => [ qw(shared array) ]);
106+
107+
# Create a thread
108+
threads->create(sub {
109+
# The thread shares the object
110+
print("Object has a $obj->{'bar'}->{'ima'}\n");
111+
112+
# Add some more data to the object
113+
push(@{$obj->{'baz'}}, qw(with five elements));
114+
115+
# Add a complex field to the object
116+
$obj->set('funk' => { 'yet' => [ qw(another hash) ] });
117+
118+
})->join();
119+
120+
# Show that the object picked up the data set by the thread
121+
print('Object has a ', join(' ', @{$obj->{'baz'}}), "\n");
122+
print('Object has yet ', join(' ', @{$obj->{'funk'}->{'yet'}}), "\n");
123+
}
124+
125+
exit(0);
126+
127+
__END__
128+
129+
=head1 NAME
130+
131+
class.pl - Example 'threadsafe' class code
132+
133+
=head1 DESCRIPTION
134+
135+
This example class illustrates how to create hash-based objects that can be
136+
shared between threads using L<threads::shared>. In addition, it shows how to
137+
permit the objects' fields to contain arbitrarily complex data structures.
138+
139+
=over
140+
141+
=item my $obj = My::Class->new('key' => $value, ...)
142+
143+
The class contructor takes parameters in the form of C<key=E<gt>value> pairs,
144+
and adds them as fields to the newly created shared object. The I<values> may
145+
be any complex data structures, and are themselves made I<shared>.
146+
147+
=item $obj->set('key' => $value)
148+
149+
This method adds/sets a field for a shared object, making the value for the
150+
field I<shared> if necessary.
151+
152+
=back
153+
154+
=head1 SEE ALSO
155+
156+
L<threads>, L<threads::shared>
157+
158+
=head1 AUTHOR
159+
160+
Jerry D. Hedden, S<E<lt>jdhedden AT cpan DOT orgE<gt>>
161+
162+
=head1 COPYRIGHT AND LICENSE
163+
164+
Copyright 2006 Jerry D. Hedden. All rights reserved.
165+
166+
This program is free software; you can redistribute it and/or modify it under
167+
the same terms as Perl itself.
168+
169+
=cut

shared.pm

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use 5.008;
55
use strict;
66
use warnings;
77

8-
our $VERSION = '1.03';
8+
our $VERSION = '1.04';
99
my $XS_VERSION = $VERSION;
1010
$VERSION = eval $VERSION;
1111

@@ -73,7 +73,7 @@ threads::shared - Perl extension for sharing data structures between threads
7373
7474
=head1 VERSION
7575
76-
This document describes threads::shared version 1.03
76+
This document describes threads::shared version 1.04
7777
7878
=head1 SYNOPSIS
7979
@@ -345,7 +345,8 @@ It is often not wise to share an object unless the class itself has been
345345
written to support sharing. For example, an object's destructor may get called
346346
multiple times, one for each thread's scope exit. Another example, is that
347347
the contents of hash-based objects will be lost due to the above mentioned
348-
limitation.
348+
limitation. See F<examples/class.pl> (in the CPAN distribution of this
349+
module) for how to create a class that supports object sharing.
349350
350351
Does not support C<splice> on arrays!
351352
@@ -367,7 +368,7 @@ L<threads::shared> Discussion Forum on CPAN:
367368
L<http://www.cpanforum.com/dist/threads-shared>
368369
369370
Annotated POD for L<threads::shared>:
370-
L<http://annocpan.org/~JDHEDDEN/threads-shared-1.03/shared.pm>
371+
L<http://annocpan.org/~JDHEDDEN/threads-shared-1.04/shared.pm>
371372
372373
L<threads>, L<perlthrtut>
373374

t/pod.t

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
use strict;
2+
use warnings;
3+
4+
BEGIN {
5+
eval {
6+
require Test::More;
7+
import Test::More 'tests' => 2;
8+
};
9+
if ($@) {
10+
print("1..0 # Skip: Test::More not available\n");
11+
exit(0);
12+
}
13+
}
14+
15+
SKIP: {
16+
eval 'use Test::Pod 1.26';
17+
skip('Test::Pod 1.26 required for testing POD', 1) if $@;
18+
19+
pod_file_ok('blib/lib/threads/shared.pm');
20+
}
21+
22+
SKIP: {
23+
eval 'use Test::Pod::Coverage 1.08';
24+
skip('Test::Pod::Coverage 1.08 required for testing POD coverage', 1) if $@;
25+
26+
pod_coverage_ok('threads::shared',
27+
{
28+
'trustme' => [
29+
],
30+
'private' => [
31+
qr/^import$/,
32+
]
33+
}
34+
);
35+
}
36+
37+
# EOF

0 commit comments

Comments
 (0)