File Coverage

blib/lib/IPC/Mmap.pm
Criterion Covered Total %
statement 49 54 90.7
branch 16 22 72.7
condition 3 5 60.0
subroutine 18 23 78.2
pod 0 18 0.0
total 86 122 70.4


line stmt bran cond sub pod time code
1             #/**
2             # Provides a minimal interface to POSIX mmap(), and its
3             # Win32 equivalent. Abstract base class that is used by
4             # the IPC::Mmap::POSIX and IPC::Mmap::Win32 implementations.
5             #

6             # Permission is granted to use this software under the same terms as Perl itself.
7             # Refer to the Perl Artistic License
8             # for details.
9             #
10             # @author D. Arnold
11             # @since 2006-05-01
12             # @self $self
13             # @exports MAP_SHARED permit the mmap'd area to be shared with other processes
14             # @exports MAP_PRIVATE do not permit the mmap'ed area to be shared with other processes
15             # @exports MAP_ANON do not use a backing file
16             # @exports MAP_ANONYMOUS same as MAP_ANON
17             # @exports MAP_FILE use a backing file for the memory mapped area
18             # @exports PROT_READ permit read access to the mmap'ed area
19             # @exports PROT_WRITE permit write access to the mmap'ed area
20             #*/
21             package IPC::Mmap;
22              
23 4     4   17590 use Carp;
  4         8  
  4         382  
24 4     4   24 use DynaLoader;
  4         7  
  4         106  
25 4     4   22 use Exporter;
  4         9  
  4         403  
26             our @ISA = qw(Exporter DynaLoader);
27             our $VERSION = '0.21';
28              
29             bootstrap IPC::Mmap $VERSION;
30              
31 4     4   23 use strict;
  4         4  
  4         153  
32 4     4   20 use warnings;
  4         4  
  4         3219  
33              
34             our @EXPORT = qw(MAP_ANON MAP_ANONYMOUS MAP_FILE MAP_PRIVATE MAP_SHARED
35             PROT_READ PROT_WRITE);
36              
37             if ($^O eq 'MSWin32') {
38             require IPC::Mmap::Win32;
39             }
40             else {
41             require IPC::Mmap::POSIX;
42             }
43             #
44             # these are generated within the appropriate XS code;
45             # gruesome, perhaps, but gets the job done
46             #
47 16     16 0 115 sub MAP_ANON { return constant('MAP_ANON', 0); }
48 0     0 0 0 sub MAP_ANONYMOUS { return constant('MAP_ANONYMOUS', 0); }
49 7     7 0 182 sub MAP_FILE { return constant('MAP_FILE', 0); }
50 0     0 0 0 sub MAP_PRIVATE { return constant('MAP_PRIVATE', 0); }
51 7     7 0 576 sub MAP_SHARED { return constant('MAP_SHARED', 0); }
52 36     36 0 25892 sub PROT_READ { return constant('PROT_READ', 0); }
53 19     19 0 398 sub PROT_WRITE { return constant('PROT_WRITE', 0); }
54              
55              
56             #/**
57             # Constructor. Maps the specified number of bytes of the specified file
58             # into the current process's address space. Read/write access protection
59             # (default is read-only), and mmap() control flags may be specified
60             # (default is MAP_SHARED). If no length is given, maps the file's current length.
61             #

62             # The specified file will be created if needed, and openned in an
63             # access mode that is compatible with the specified access protection.
64             # If the size of the file is less than the specified length, and the access flags
65             # include write access, the file will be extended with NUL characters to the
66             # specified length.
67             #

68             # Note that for Win32, the specified file is used as a "namespace",
69             # rather than physical file, if an "anonymous" mmap() is requested.
70             #

71             # On POSIX platforms, an anonymous, private shared memory region
72             # can be created (to be inherited by any fork()'ed
73             # child processes) by using a zero-length filename, and
74             # "private" (MAP_PRIVATE) mmap() flags.
75             #

76             # On Win32 platforms, the default behavior is to create a "namespace", and use the
77             # Windows swap file for the backing file. However, by including MAP_FILE in the
78             # mmap() flags parameter, the specified file will be opened and/or created,
79             # and used for the backing file, rather than the system swap file.
80             #
81             # @param $filename name of file (or namespace) to be mapped
82             # @param $length optional number of bytes to be mapped
83             # @param $protflags optional read/write access flags
84             # @param $mmapflags optional mmap() control flags
85             #
86             # @return the IPC::Mmap object on success; undef on failure
87             #*/
88             sub new {
89 8     8 0 76 my ($class, $file, $length, $prot, $mmap) = @_;
90              
91 8 50       34 $length = 0 unless defined($length);
92 8 50       26 $prot = PROT_READ unless defined($prot);
93 8 50       31 $mmap = MAP_SHARED unless defined($mmap);
94             #
95             # we're just a factory for the platform-specific objects
96             #
97 8 50       212 return ($^O eq 'MSWin32') ?
98             IPC::Mmap::Win32->new($file, $length, $prot, $mmap) :
99             IPC::Mmap::POSIX->new($file, $length, $prot, $mmap);
100             }
101              
102             #/**
103             # Reads data from a specific area of the mmap()'ed file.
104             #
105             # @param $data scalar to receive the data
106             # @param $offset optional offset into mmap'ed area; default is zero
107             # @param $length optional length to read; default is from the offset to the end of the file
108             #
109             # @return the number of bytes actually read on success; undef on failure
110             #*/
111             sub read {
112 12     12 0 1566 my $self = shift;
113              
114 12 100       43 croak "Invalid access on write-only region",
115             return undef
116             unless $self->{_access} & PROT_READ;
117              
118 11   50     64 my $off = ($_[1] || 0) + $self->{_slop};
119 11   66     87 my $len = $_[2] || $self->{_maxlen};
120              
121 11 100       57 croak "read failed: offset exceeds region length",
122             return undef
123             if ($off >= $self->{_maxlen});
124              
125 9         122 return mmap_read($self->{_addr}, $self->{_maxlen},
126             $off, $_[0], $len);
127             }
128              
129             #/**
130             # Write data to the mmap()'ed region.
131             # Writes the specified number of bytes of the specified scalar variable
132             # to the mmap'ed region starting at the specified offset. If not specified,
133             # offset defaults to zero, and length> defaults to the length of the scalar.
134             # If the specified length exceeds the available length of the mmap'ed region
135             # starting from the offset, only the available region length will be written.
136             #
137             # @param $data the data to be written
138             # @param $offset optional offset where the data should be written; default is zero
139             # @param $length optional length of the data to write; default is the length of the data
140             #
141             # @return on success, returns the actual number of bytes written; returns undef
142             # if the offset exceeds the length of the region
143             #*/
144             sub write {
145 10     10 0 1298 my ($self, $var, $off, $len) = @_;
146              
147 10 100       41 croak "Invalid access on read-only region",
148             return undef
149             unless $self->{_access} & PROT_WRITE;
150              
151 9 50       35 $off = 0 unless defined($off);
152 9         20 $off += $self->{_slop};
153 9 100       30 $len = length($var) unless $len;
154              
155 9 100       69 croak "write failed: offset exceeds region length",
156             return undef
157             if ($off >= $self->{_maxlen});
158              
159 8         81 return mmap_write($self->{_addr}, $self->{_maxlen},
160             $off, $var, $len);
161             }
162             #/**
163             # Packs a list of values according to the specified pack string, and writes
164             # the binary result to the mmap'ed region at specified offset.
165             # If the offset plus the packed data length extends beyond the end of the
166             # region, only the available number of bytes will be written.
167             #
168             # @param $offset offset to write the packed data
169             # @param $packstr pack string to be applied to the data
170             # @param @values list of values to pack and write
171             #
172             # @return undef if $offset is beyond the end of the mmap'ed region; otherwise,
173             # the total number of bytes written
174             #*/
175             sub pack {
176 2     2 0 225 my $self = shift;
177 2         5 my $off = shift;
178 2         11 my $packstr = shift;
179 2         53 return $self->write(CORE::pack($packstr, @_), $off);
180             }
181             #/**
182             # Read the specified number of bytes starting at the specified offset
183             # and unpack into Perl scalars using the specified pack() string.
184             #
185             # @param $offset offset to start reading from
186             # @param $length number of bytes to read
187             # @param $packstr pack string to apply to the read data
188             #
189             # @return on success, the list of unpacked values; undef on failure
190             #*/
191             sub unpack {
192 2     2 0 207 my ($self, $off, $length, $packstr) = @_;
193 2         19 my $val;
194             return undef
195 2 50       21 unless $self->read($val, $off, $length);
196 2         59 return CORE::unpack($packstr, $val);
197             }
198              
199             #/**
200             # Locks the mmap'ed region. Pure virtual function to be implemented
201             # in the OS-specific implementation subclass.
202             #*/
203 0     0 0 0 sub lock { }
204              
205             #/**
206             # Unlock the mmap'ed region. Pure virtual function
207             # to be implemented in the OS-specific implementation
208             # subclass.
209             #
210             #*/
211 0     0 0 0 sub unlock { }
212             #/**
213             # Get the filename (or namespace on Win32) for the mmap'ed file.
214             #
215             # @return the mmap'ed filename.
216             #*/
217 1     1 0 185 sub getFilename { return $_[0]->{_file}; }
218              
219             #/**
220             # Get the filehandle for the mmap'ed file. If MAP_ANON
221             # was specified for POSIX platforms, or MAP_FILE was not specified
222             # on Win32 platforms, returns undef.
223             #
224             # @return the file handle used for the mmap'ed file.
225             #*/
226 0     0 0 0 sub getFileHandle { return $_[0]->{_fh}; }
227             #/**
228             # Get the length of the mmap'ed region
229             #
230             # @return the length of the mmap()ed region.
231             #*/
232 2     2 0 326 sub getLength { return $_[0]->{_maxlen}; }
233             #/**
234             # Get the base address to which the mmap'ed region was mapped.
235             #
236             # @return the address of the mmap()ed region.
237             #*/
238 1     1 0 219 sub getAddress { return $_[0]->{_addr}; }
239              
240              
241             1;