File Coverage

blib/lib/ExtUtils/XSpp/Plugin/Cloning.pm
Criterion Covered Total %
statement 12 39 30.7
branch 0 6 0.0
condition n/a
subroutine 4 8 50.0
pod 0 3 0.0
total 16 56 28.5


line stmt bran cond sub pod time code
1             package ExtUtils::XSpp::Plugin::Cloning;
2 1     1   703 use strict;
  1         2  
  1         31  
3 1     1   4 use warnings;
  1         1  
  1         40  
4              
5             our $VERSION = '0.02';
6              
7 1     1   12 use Carp ();
  1         2  
  1         11  
8 1     1   699 use ExtUtils::XSpp ();
  1         122750  
  1         407  
9              
10             =head1 NAME
11              
12             ExtUtils::XSpp::Plugin::Cloning - An XS++ plugin for controlling cloning on thread creation
13              
14             =head1 SYNOPSIS
15              
16             Use it in your XS++ code as follows. No other interface required.
17              
18             %module{Your::Module}
19            
20             %loadplugin{Cloning}
21            
22             # Objects of this class will just be undef in a cloned interpreter
23             class MyThreadSafeClass {
24             %PreventCloning;
25             ...
26             };
27            
28             # TODO More to come
29              
30             =head1 DESCRIPTION
31              
32             C is a plugin for C (See L)
33             for controlling the behavior of a class's objects when the interpreter/thread they
34             live in is cloned.
35              
36             Since C's plugin interface is considered experimental, so is this
37             module!
38              
39             =head1 DIRECTIVES
40              
41             =head2 C<%PreventCloning>
42              
43             Specify this directive inside your class to prevent objects of the class
44             from being cloned on thread spawning. They will simply be undefined in the
45             new interperter/thread.
46              
47             This defines a new C method in the given class that prevents
48             the instances from being cloned. Note that due to this implementation detail,
49             the effect of the C<%PreventCloning> directive is inheritable.
50              
51             =cut
52              
53             sub new {
54 0     0 0   my $class = shift;
55 0           my $self = {@_};
56 0           bless $self => $class;
57 0           return $self;
58             }
59              
60             sub register_plugin {
61 0     0 0   my ($class, $parser) = @_;
62              
63 0           $parser->add_class_tag_plugin(
64             plugin => $class->new,
65             tag => 'PreventCloning',
66             );
67             }
68              
69             sub handle_class_tag {
70 0     0 0   my ($self, $class, $tag, %args) = @_;
71              
72 0 0         if ($tag eq 'PreventCloning') {
73 0           $self->_handle_prevent_cloning($class);
74 0           return 1;
75             }
76 0           return();
77             }
78              
79             sub _handle_prevent_cloning {
80 0     0     my ($self, $class) = @_;
81 0           my $class_name = $class->perl_name;
82              
83 0           my $cpp_name = '__CLONE';
84 0           foreach my $method (@{$class->methods}) {
  0            
85 0 0         if ($method->name eq 'CLONE_SKIP') {
86 0           Carp::confess("Perl class '$class_name' already has a 'CLONE_SKIP' method");
87             }
88 0 0         if ($cpp_name eq $method->cpp_name) {
89 0           $cpp_name .= '_';
90             }
91             }
92              
93 0           my $inttype = ExtUtils::XSpp::Node::Type->new(base => 'int');
94 0           my $chartype = ExtUtils::XSpp::Node::Type->new(base => 'char', pointer => '*');
95 0           my $arg = ExtUtils::XSpp::Node::Argument->new(
96             type => $chartype,
97             name => 'class_name',
98             );
99 0           my $meth = ExtUtils::XSpp::Node::Function->new(
100             class => $class,
101             cpp_name => $cpp_name,
102             perl_name => 'CLONE_SKIP',
103             arguments => [$arg],
104             ret_type => $inttype,
105             code => ["RETVAL = 1;\n"],
106             );
107 0           $meth->set_static("package_static");
108 0           $class->add_methods($meth);
109              
110 0           return;
111             }
112              
113             1;
114             __END__