Re: Exceptions in IPC::Open2
[p5sagit/p5-mst-13.2.git] / pod / perltie.pod
index 962a7e3..da4fbe9 100644 (file)
@@ -33,7 +33,7 @@ In the tie() call, C<VARIABLE> is the name of the variable to be
 enchanted.  C<CLASSNAME> is the name of a class implementing objects of
 the correct type.  Any additional arguments in the C<LIST> are passed to
 the appropriate constructor method for that class--meaning TIESCALAR(),
-TIEARRAY(), TIEHASH() or TIEHANDLE().  (Typically these are arguments
+TIEARRAY(), TIEHASH(), or TIEHANDLE().  (Typically these are arguments
 such as might be passed to the dbminit() function of C.) The object
 returned by the "new" method is also returned by the tie() function,
 which would be useful if you wanted to access other methods in
@@ -60,10 +60,10 @@ And now whenever either of those variables is accessed, its current
 system priority is retrieved and returned.  If those variables are set,
 then the process's priority is changed!
 
-We'll use Jarkko Hietaniemi F<E<lt>Jarkko.Hietaniemi@hut.fiE<gt>>'s
-BSD::Resource class (not included) to access the PRIO_PROCESS, PRIO_MIN,
-and PRIO_MAX constants from your system, as well as the getpriority() and
-setpriority() system calls.  Here's the preamble of the class.
+We'll use Jarkko Hietaniemi <F<jhi@iki.fi>>'s BSD::Resource class (not
+included) to access the PRIO_PROCESS, PRIO_MIN, and PRIO_MAX constants
+from your system, as well as the getpriority() and setpriority() system
+calls.  Here's the preamble of the class.
 
     package Nice;
     use Carp;
@@ -180,17 +180,26 @@ TIESCALAR classes are certainly possible.
 =head2 Tying Arrays
 
 A class implementing a tied ordinary array should define the following
-methods: TIEARRAY, FETCH, STORE, and perhaps DESTROY.
+methods: TIEARRAY, FETCH, STORE, FETCHSIZE, STORESIZE and perhaps DESTROY. 
 
-B<WARNING>: Tied arrays are I<incomplete>.  They are also distinctly lacking
-something for the C<$#ARRAY> access (which is hard, as it's an lvalue), as
-well as the other obvious array functions, like push(), pop(), shift(),
-unshift(), and splice().
+FETCHSIZE and STORESIZE are used to provide C<$#array> and
+equivalent C<scalar(@array)> access.
+    
+The methods POP, PUSH, SHIFT, UNSHIFT, SPLICE are required if the perl
+operator with the corresponding (but lowercase) name is to operate on the
+tied array. The B<Tie::Array> class can be used as a base class to implement
+these in terms of the basic five methods above.  
+
+In addition EXTEND will be called when perl would have pre-extended 
+allocation in a real array.
+
+This means that tied arrays are now I<complete>. The example below needs
+upgrading to illustrate this. (The documentation in B<Tie::Array> is more
+complete.)
 
 For this discussion, we'll implement an array whose indices are fixed at
 its creation.  If you try to access anything beyond those bounds, you'll
-take an exception.  (Well, if you access an individual element; an
-aggregate assignment would be missed.) For example:
+take an exception.  For example:
 
     require Bounded_Array;
     tie @ary, 'Bounded_Array', 2;
@@ -293,19 +302,18 @@ the following output demonstrates:
 
 =head2 Tying Hashes
 
-As the first Perl data type to be tied (see dbmopen()), associative arrays
-have the most complete and useful tie() implementation.  A class
-implementing a tied associative array should define the following
-methods:  TIEHASH is the constructor.  FETCH and STORE access the key and
-value pairs.  EXISTS reports whether a key is present in the hash, and
-DELETE deletes one.  CLEAR empties the hash by deleting all the key and
-value pairs.  FIRSTKEY and NEXTKEY implement the keys() and each()
-functions to iterate over all the keys.  And DESTROY is called when the
-tied variable is garbage collected.
+As the first Perl data type to be tied (see dbmopen()), hashes have the
+most complete and useful tie() implementation.  A class implementing a
+tied hash should define the following methods: TIEHASH is the constructor.
+FETCH and STORE access the key and value pairs.  EXISTS reports whether a
+key is present in the hash, and DELETE deletes one.  CLEAR empties the
+hash by deleting all the key and value pairs.  FIRSTKEY and NEXTKEY
+implement the keys() and each() functions to iterate over all the keys.
+And DESTROY is called when the tied variable is garbage collected.
 
-If this seems like a lot, then feel free to inherit from
-merely the standard Tie::Hash module for most of your methods, redefining only
-the interesting ones.  See L<Tie::Hash> for details.
+If this seems like a lot, then feel free to inherit from merely the
+standard Tie::Hash module for most of your methods, redefining only the
+interesting ones.  See L<Tie::Hash> for details.
 
 Remember that Perl distinguishes between a key not existing in the hash,
 and the key existing in the hash but having a corresponding value of
@@ -414,7 +422,7 @@ Here's the constructor:
 It's probably worth mentioning that if you're going to filetest the
 return values out of a readdir, you'd better prepend the directory
 in question.  Otherwise, because we didn't chdir() there, it would
-have been testing the wrong file.  
+have been testing the wrong file.
 
 =item FETCH this, key
 
@@ -595,9 +603,9 @@ or have auxiliary state to clean up.  Here's a very simple function:
 
 =back
 
-Note that functions such as keys() and values() may return huge array
-values when used on large objects, like DBM files.  You may prefer to
-use the each() function to iterate over such.  Example:
+Note that functions such as keys() and values() may return huge lists
+when used on large objects, like DBM files.  You may prefer to use the
+each() function to iterate over such.  Example:
 
     # print out history file offsets
     use NDBM_File;
@@ -611,8 +619,9 @@ use the each() function to iterate over such.  Example:
 
 This is partially implemented now.
 
-A class implementing a tied filehandle should define the following methods:
-TIEHANDLE, PRINT and/or READLINE, and possibly DESTROY.
+A class implementing a tied filehandle should define the following
+methods: TIEHANDLE, at least one of PRINT, PRINTF, WRITE, READLINE, GETC,
+READ, and possibly CLOSE and DESTROY.
 
 It is especially useful when perl is embedded in some other program,
 where output to STDOUT and STDERR may have to be redirected in some
@@ -628,25 +637,74 @@ In our example we're going to create a shouting handle.
 
 This is the constructor for the class.  That means it is expected to
 return a blessed reference of some sort. The reference can be used to
-hold some internal information. We won't use it in out example.
+hold some internal information.
 
     sub TIEHANDLE { print "<shout>\n"; my $i; bless \$i, shift }
 
+=item WRITE this, LIST
+
+This method will be called when the handle is written to via the
+C<syswrite> function.
+
+    sub WRITE {
+       $r = shift;
+       my($buf,$len,$offset) = @_;
+       print "WRITE called, \$buf=$buf, \$len=$len, \$offset=$offset";
+    }
+
 =item PRINT this, LIST
 
-This method will be triggered every time the tied handle is printed to.
+This method will be triggered every time the tied handle is printed to
+with the C<print()> function.
 Beyond its self reference it also expects the list that was passed to
 the print function.
 
     sub PRINT { $r = shift; $$r++; print join($,,map(uc($_),@_)),$\ }
 
+=item PRINTF this, LIST
+
+This method will be triggered every time the tied handle is printed to
+with the C<printf()> function.
+Beyond its self reference it also expects the format and list that was
+passed to the printf function.
+
+    sub PRINTF {
+        shift;
+        my $fmt = shift;
+        print sprintf($fmt, @_)."\n";
+    }
+
+=item READ this, LIST
+
+This method will be called when the handle is read from via the C<read>
+or C<sysread> functions.
+
+    sub READ {
+       $r = shift;
+       my($buf,$len,$offset) = @_;
+       print "READ called, \$buf=$buf, \$len=$len, \$offset=$offset";
+    }
+
 =item READLINE this
 
-This method will be called when the handle is read from. The method
-should return undef when there is no more data.
+This method will be called when the handle is read from via <HANDLE>.
+The method should return undef when there is no more data.
 
     sub READLINE { $r = shift; "PRINT called $$r times\n"; }
 
+=item GETC this
+
+This method will be called when the C<getc> function is called.
+
+    sub GETC { print "Don't GETC, Get Perl"; return "a"; }
+
+=item CLOSE this
+
+This method will be called when the handle is closed via the C<close>
+function.
+
+    sub CLOSE { print "CLOSE called.\n" }
+
 =item DESTROY this
 
 As with the other types of ties, this method will be called when the
@@ -665,6 +723,133 @@ Here's how to use our little example:
     print FOO $a, " plus ", $b, " equals ", $a + $b, "\n";
     print <FOO>;
 
+=head2 The C<untie> Gotcha
+
+If you intend making use of the object returned from either tie() or
+tied(), and if the tie's target class defines a destructor, there is a
+subtle gotcha you I<must> guard against.
+
+As setup, consider this (admittedly rather contrived) example of a
+tie; all it does is use a file to keep a log of the values assigned to
+a scalar.
+
+    package Remember;
+
+    use strict;
+    use IO::File;
+
+    sub TIESCALAR {
+        my $class = shift;
+        my $filename = shift;
+        my $handle = new IO::File "> $filename"
+                         or die "Cannot open $filename: $!\n";
+
+        print $handle "The Start\n";
+        bless {FH => $handle, Value => 0}, $class;
+    }
+
+    sub FETCH {
+        my $self = shift;
+        return $self->{Value};
+    }
+
+    sub STORE {
+        my $self = shift;
+        my $value = shift;
+        my $handle = $self->{FH};
+        print $handle "$value\n";
+        $self->{Value} = $value;
+    }
+
+    sub DESTROY {
+        my $self = shift;
+        my $handle = $self->{FH};
+        print $handle "The End\n";
+        close $handle;
+    }
+
+    1;
+
+Here is an example that makes use of this tie:
+
+    use strict;
+    use Remember;
+
+    my $fred;
+    tie $fred, 'Remember', 'myfile.txt';
+    $fred = 1;
+    $fred = 4;
+    $fred = 5;
+    untie $fred;
+    system "cat myfile.txt";
+
+This is the output when it is executed:
+
+    The Start
+    1
+    4
+    5
+    The End
+
+So far so good.  Those of you who have been paying attention will have
+spotted that the tied object hasn't been used so far.  So lets add an
+extra method to the Remember class to allow comments to be included in
+the file -- say, something like this:
+
+    sub comment {
+        my $self = shift;
+        my $text = shift;
+        my $handle = $self->{FH};
+        print $handle $text, "\n";
+    }
+
+And here is the previous example modified to use the C<comment> method
+(which requires the tied object):
+
+    use strict;
+    use Remember;
+
+    my ($fred, $x);
+    $x = tie $fred, 'Remember', 'myfile.txt';
+    $fred = 1;
+    $fred = 4;
+    comment $x "changing...";
+    $fred = 5;
+    untie $fred;
+    system "cat myfile.txt";
+
+When this code is executed there is no output.  Here's why:
+
+When a variable is tied, it is associated with the object which is the
+return value of the TIESCALAR, TIEARRAY, or TIEHASH function.  This
+object normally has only one reference, namely, the implicit reference
+from the tied variable.  When untie() is called, that reference is
+destroyed.  Then, as in the first example above, the object's
+destructor (DESTROY) is called, which is normal for objects that have
+no more valid references; and thus the file is closed.
+
+In the second example, however, we have stored another reference to
+the tied object in C<$x>.  That means that when untie() gets called
+there will still be a valid reference to the object in existence, so
+the destructor is not called at that time, and thus the file is not
+closed.  The reason there is no output is because the file buffers
+have not been flushed to disk.
+
+Now that you know what the problem is, what can you do to avoid it?
+Well, the good old C<-w> flag will spot any instances where you call
+untie() and there are still valid references to the tied object.  If
+the second script above is run with the C<-w> flag, Perl prints this
+warning message:
+
+    untie attempted while 1 inner references still exist
+
+To get the script to work properly and silence the warning make sure
+there are no valid references to the tied object I<before> untie() is
+called:
+
+    undef $x;
+    untie $fred;
+
 =head1 SEE ALSO
 
 See L<DB_File> or L<Config> for some interesting tie() implementations.
@@ -681,11 +866,11 @@ hashes) to a dbm file.  The first problem is that all but GDBM and
 Berkeley DB have size limitations, but beyond that, you also have problems
 with how references are to be represented on disk.  One experimental
 module that does attempt to address this need partially is the MLDBM
-module.  Check your nearest CPAN site as described in L<perlmod> for
+module.  Check your nearest CPAN site as described in L<perlmodlib> for
 source code to MLDBM.
 
 =head1 AUTHOR
 
 Tom Christiansen
 
-TIEHANDLE by Sven Verdoolaege E<lt>F<skimo@dns.ufsia.ac.be>E<gt>
+TIEHANDLE by Sven Verdoolaege <F<skimo@dns.ufsia.ac.be>> and Doug MacEachern <F<dougm@osf.org>>