*nix Documentation Project
·  Home
 +   man pages
·  Linux HOWTOs
·  FreeBSD Tips
·  *niX Forums

  man pages->IRIX man pages -> perltie (1)              
Title
Content
Arch
Section
 

Contents


PERLTIE(1)							    PERLTIE(1)


NAME    [Toc]    [Back]

     perltie - how to hide an object class in a	simple variable

SYNOPSIS    [Toc]    [Back]

      tie VARIABLE, CLASSNAME, LIST

      $object =	tied VARIABLE

      untie VARIABLE

DESCRIPTION    [Toc]    [Back]

     Prior to release 5.0 of Perl, a programmer	could use dbmopen() to connect
     an	on-disk	database in the	standard Unix dbm(3x) format magically to a
     %HASH in their program.  However, their Perl was either built with	one
     particular	dbm library or another,	but not	both, and you couldn't extend
     this mechanism to other packages or types of variables.

     Now you can.

     The tie() function	binds a	variable to a class (package) that will
     provide the implementation	for access methods for that variable.  Once
     this magic	has been performed, accessing a	tied variable automatically
     triggers method calls in the proper class.	 All of	the complexity of the
     class is hidden behind magic methods calls.  The method names are in ALL
     CAPS, which is a convention that Perl uses	to indicate that they're
     called implicitly rather than explicitly--just like the BEGIN() and END()
     functions.

     In	the tie() call,	VARIABLE is the	name of	the variable to	be enchanted.
     CLASSNAME is the name of a	class implementing objects of the correct
     type.  Any	additional arguments in	the LIST are passed to the appropriate
     constructor method	for that class--meaning	TIESCALAR(), 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 CLASSNAME.	(You don't
     actually have to return a reference to a right "type" (e.g., HASH or
     CLASSNAME)	so long	as it's	a properly blessed object.)  You can also
     retrieve a	reference to the underlying object using the tied() function.

     Unlike dbmopen(), the tie() function will not use or require a module for
     you--you need to do that explicitly yourself.

     Tying Scalars    [Toc]    [Back]

     A class implementing a tied scalar	should define the following methods:
     TIESCALAR,	FETCH, STORE, and possibly DESTROY.

     Let's look	at each	in turn, using as an example a tie class for scalars
     that allows the user to do	something like:




									Page 1






PERLTIE(1)							    PERLTIE(1)



	 tie $his_speed, 'Nice', getppid();
	 tie $my_speed,	 'Nice', $$;

     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 <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;
	 use BSD::Resource;
	 use strict;
	 $Nice::DEBUG =	0 unless defined $Nice::DEBUG;


     TIESCALAR classname, LIST
	  This is the constructor for the class.  That means it	is expected to
	  return a blessed reference to	a new scalar (probably anonymous) that
	  it's creating.  For example:

	      sub TIESCALAR {
		  my $class = shift;
		  my $pid = shift || $$; # 0 means me

		  if ($pid !~ /^\d+$/) {
		      carp "Nice::Tie::Scalar got non-numeric pid $pid"	if $^W;
		      return undef;
		  }

		  unless (kill 0, $pid)	{ # EPERM or ERSCH, no doubt
		      carp "Nice::Tie::Scalar got bad pid $pid:	$!" if $^W;
		      return undef;
		  }

		  return bless \$pid, $class;
	      }

	  This tie class has chosen to return an error rather than raising an
	  exception if its constructor should fail.  While this	is how
	  dbmopen() works, other classes may well not wish to be so forgiving.
	  It checks the	global variable	$^W to see whether to emit a bit of
	  noise	anyway.

     FETCH this
	  This method will be triggered	every time the tied variable is
	  accessed (read).  It takes no	arguments beyond its self reference,
	  which	is the object representing the scalar we're dealing with.
	  Because in this case we're using just	a SCALAR ref for the tied



									Page 2






PERLTIE(1)							    PERLTIE(1)



	  scalar object, a simple $$self allows	the method to get at the real
	  value	stored there.  In our example below, that real value is	the
	  process ID to	which we've tied our variable.

	      sub FETCH	{
		  my $self = shift;
		  confess "wrong type" unless ref $self;
		  croak	"usage error" if @_;
		  my $nicety;
		  local($!) = 0;
		  $nicety = getpriority(PRIO_PROCESS, $$self);
		  if ($!) { croak "getpriority failed: $!" }
		  return $nicety;
	      }

	  This time we've decided to blow up (raise an exception) if the
	  renice fails--there's	no place for us	to return an error otherwise,
	  and it's probably the	right thing to do.

     STORE this, value
	  This method will be triggered	every time the tied variable is	set
	  (assigned).  Beyond its self reference, it also expects one (and
	  only one) argument--the new value the	user is	trying to assign.

	      sub STORE	{
		  my $self = shift;
		  confess "wrong type" unless ref $self;
		  my $new_nicety = shift;
		  croak	"usage error" if @_;

		  if ($new_nicety < PRIO_MIN) {
		      carp sprintf
			"WARNING: priority %d less than	minimum	system priority	%d",
			    $new_nicety, PRIO_MIN if $^W;
		      $new_nicety = PRIO_MIN;
		  }

		  if ($new_nicety > PRIO_MAX) {
		      carp sprintf
			"WARNING: priority %d greater than maximum system priority %d",
			    $new_nicety, PRIO_MAX if $^W;
		      $new_nicety = PRIO_MAX;
		  }

		  unless (defined setpriority(PRIO_PROCESS, $$self, $new_nicety)) {
		      confess "setpriority failed: $!";
		  }
		  return $new_nicety;
	      }






									Page 3






PERLTIE(1)							    PERLTIE(1)



     DESTROY this
	  This method will be triggered	when the tied variable needs to	be
	  destructed.  As with other object classes, such a method is seldom
	  necessary, because Perl deallocates its moribund object's memory for
	  you automatically--this isn't	C++, you know.	We'll use a DESTROY
	  method here for debugging purposes only.

	      sub DESTROY {
		  my $self = shift;
		  confess "wrong type" unless ref $self;
		  carp "[ Nice::DESTROY	pid $$self ]" if $Nice::DEBUG;
	      }


     That's about all there is to it.  Actually, it's more than	all there is
     to	it, because we've done a few nice things here for the sake of
     completeness, robustness, and general aesthetics.	Simpler	TIESCALAR
     classes are certainly possible.

     Tying Arrays    [Toc]    [Back]

     A class implementing a tied ordinary array	should define the following
     methods: TIEARRAY,	FETCH, STORE, and perhaps DESTROY.

     WARNING: Tied arrays are incomplete.  They	are also distinctly lacking
     something for the $#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().

     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:

	 require Bounded_Array;
	 tie @ary, 'Bounded_Array', 2;
	 $| = 1;
	 for $i	(0 .. 10) {
	     print "setting index $i: ";
	     $ary[$i] =	10 * $i;
	     $ary[$i] =	10 * $i;
	     print "value of elt $i now	$ary[$i]\n";
	 }

     The preamble code for the class is	as follows:

	 package Bounded_Array;
	 use Carp;
	 use strict;






									Page 4






PERLTIE(1)							    PERLTIE(1)



     TIEARRAY classname, LIST
	  This is the constructor for the class.  That means it	is expected to
	  return a blessed reference through which the new array (probably an
	  anonymous ARRAY ref) will be accessed.

	  In our example, just to show you that	you don't really have to
	  return an ARRAY reference, we'll choose a HASH reference to
	  represent our	object.	 A HASH	works out well as a generic record
	  type:	the {BOUND} field will store the maximum bound allowed,	and
	  the {ARRAY} field will hold the true ARRAY ref.  If someone outside
	  the class tries to dereference the object returned (doubtless
	  thinking it an ARRAY ref), they'll blow up.  This just goes to show
	  you that you should respect an object's privacy.

	      sub TIEARRAY {
		  my $class = shift;
		  my $bound = shift;
		  confess "usage: tie(\@ary, 'Bounded_Array', max_subscript)"
		      if @_ || $bound =~ /\D/;
		  return bless {
		      BOUND => $bound,
		      ARRAY => [],
		  }, $class;
	      }


     FETCH this, index
	  This method will be triggered	every time an individual element the
	  tied array is	accessed (read).  It takes one argument	beyond its
	  self reference: the index whose value	we're trying to	fetch.

	      sub FETCH	{
		my($self,$idx) = @_;
		if ($idx > $self->{BOUND}) {
		  confess "Array OOB: $idx > $self->{BOUND}";
		}
		return $self->{ARRAY}[$idx];
	      }

	  As you may have noticed, the name of the FETCH method	(et al.) is
	  the same for all accesses, even though the constructors differ in
	  names	(TIESCALAR vs TIEARRAY).  While	in theory you could have the
	  same class servicing several tied types, in practice this becomes
	  cumbersome, and it's easiest to keep them at simply one tie type per
	  class.

     STORE this, index,	value
	  This method will be triggered	every time an element in the tied
	  array	is set (written).  It takes two	arguments beyond its self
	  reference: the index at which	we're trying to	store something	and
	  the value we're trying to put	there.	For example:




									Page 5






PERLTIE(1)							    PERLTIE(1)



	      sub STORE	{
		my($self, $idx,	$value)	= @_;
		print "[STORE $value at	$idx]\n" if _debug;
		if ($idx > $self->{BOUND} ) {
		  confess "Array OOB: $idx > $self->{BOUND}";
		}
		return $self->{ARRAY}[$idx] = $value;
	      }


     DESTROY this
	  This method will be triggered	when the tied variable needs to	be
	  destructed.  As with the scalar tie class, this is almost never
	  needed in a language that does its own garbage collection, so	this
	  time we'll just leave	it out.

     The code we presented at the top of the tied array	class accesses many
     elements of the array, far	more than we've	set the	bounds to.  Therefore,
     it	will blow up once they try to access beyond the	2nd element of @ary,
     as	the following output demonstrates:

	 setting index 0: value	of elt 0 now 0
	 setting index 1: value	of elt 1 now 10
	 setting index 2: value	of elt 2 now 20
	 setting index 3: Array	OOB: 3 > 2 at Bounded_Array.pm line 39
		 Bounded_Array::FETCH called at	testba line 12


     Tying Hashes    [Toc]    [Back]

     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 the	Tie::Hash manpage 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
     undef.  The two possibilities can be tested with the exists() and
     defined() functions.

     Here's an example of a somewhat interesting tied hash class:  it gives
     you a hash	representing a particular user's dot files.  You index into
     the hash with the name of the file	(minus the dot)	and you	get back that



									Page 6






PERLTIE(1)							    PERLTIE(1)



     dot file's	contents.  For example:

	 use DotFiles;
	 tie %dot, 'DotFiles';
	 if ( $dot{profile} =~ /MANPATH/ ||
	      $dot{login}   =~ /MANPATH/ ||
	      $dot{cshrc}   =~ /MANPATH/    )
	 {
	     print "you	seem to	set your MANPATH\n";
	 }

     Or	here's another sample of using our tied	class:

	 tie %him, 'DotFiles', 'daemon';
	 foreach $f ( keys %him	) {
	     printf "daemon dot	file %s	is size	%d\n",
		 $f, length $him{$f};
	 }

     In	our tied hash DotFiles example,	we use a regular hash for the object
     containing	several	important fields, of which only	the {LIST} field will
     be	what the user thinks of	as the real hash.

     USER whose	dot files this object represents

     HOME where	those dot files	live

     CLOBBER
	  whether we should try	to change or remove those dot files

     LIST the hash of dot file names and content mappings

     Here's the	start of Dotfiles.pm:

	 package DotFiles;
	 use Carp;
	 sub whowasi { (caller(1))[3] .	'()' }
	 my $DEBUG = 0;
	 sub debug { $DEBUG = @_ ? shift : 1 }

     For our example, we want to be able to emit debugging info	to help	in
     tracing during development.  We keep also one convenience function	around
     internally	to help	print out warnings; whowasi() returns the function
     name that calls it.

     Here are the methods for the DotFiles tied	hash.

     TIEHASH classname,	LIST
	  This is the constructor for the class.  That means it	is expected to
	  return a blessed reference through which the new object (probably
	  but not necessarily an anonymous hash) will be accessed.




									Page 7






PERLTIE(1)							    PERLTIE(1)



	  Here's the constructor:

	      sub TIEHASH {
		  my $self = shift;
		  my $user = shift || $>;
		  my $dotdir = shift ||	'';
		  croak	"usage:	@{[&whowasi]} [USER [DOTDIR]]" if @_;
		  $user	= getpwuid($user) if $user =~ /^\d+$/;
		  my $dir = (getpwnam($user))[7]
			  || croak "@{[&whowasi]}: no user $user";
		  $dir .= "/$dotdir" if	$dotdir;

		  my $node = {
		      USER    => $user,
		      HOME    => $dir,
		      LIST    => {},
		      CLOBBER => 0,
		  };

		  opendir(DIR, $dir)
			  || croak "@{[&whowasi]}: can't opendir $dir: $!";
		  foreach $dot ( grep /^\./ && -f "$dir/$_", readdir(DIR)) {
		      $dot =~ s/^\.//;
		      $node->{LIST}{$dot} = undef;
		  }
		  closedir DIR;
		  return bless $node, $self;
	      }

	  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.

     FETCH this, key
	  This method will be triggered	every time an element in the tied hash
	  is accessed (read).  It takes	one argument beyond its	self
	  reference: the key whose value we're trying to fetch.

	  Here's the fetch for our DotFiles example.

	      sub FETCH	{
		  carp &whowasi	if $DEBUG;
		  my $self = shift;
		  my $dot = shift;
		  my $dir = $self->{HOME};
		  my $file = "$dir/.$dot";

		  unless (exists $self->{LIST}->{$dot} || -f $file) {
		      carp "@{[&whowasi]}: no $dot file" if $DEBUG;
		      return undef;
		  }



									Page 8






PERLTIE(1)							    PERLTIE(1)



		  if (defined $self->{LIST}->{$dot}) {
		      return $self->{LIST}->{$dot};
		  } else {
		      return $self->{LIST}->{$dot} = `cat $dir/.$dot`;
		  }
	      }

	  It was easy to write by having it call the Unix cat(1) command, but
	  it would probably be more portable to	open the file manually (and
	  somewhat more	efficient).  Of	course,	because	dot files are a	Unixy
	  concept, we're not that concerned.

     STORE this, key, value
	  This method will be triggered	every time an element in the tied hash
	  is set (written).  It	takes two arguments beyond its self reference:
	  the index at which we're trying to store something, and the value
	  we're	trying to put there.

	  Here in our DotFiles example,	we'll be careful not to	let them try
	  to overwrite the file	unless they've called the clobber() method on
	  the original object reference	returned by tie().

	      sub STORE	{
		  carp &whowasi	if $DEBUG;
		  my $self = shift;
		  my $dot = shift;
		  my $value = shift;
		  my $file = $self->{HOME} . "/.$dot";
		  my $user = $self->{USER};

		  croak	"@{[&whowasi]}:	$file not clobberable"
		      unless $self->{CLOBBER};

		  open(F, "> $file") ||	croak "can't open $file: $!";
		  print	F $value;
		  close(F);
	      }

	  If they wanted to clobber something, they might say:

	      $ob = tie	%daemon_dots, 'daemon';
	      $ob->clobber(1);
	      $daemon_dots{signature} =	"A true	daemon\n";

	  Another way to lay hands on a	reference to the underlying object is
	  to use the tied() function, so they might alternately	have set
	  clobber using:

	      tie %daemon_dots,	'daemon';
	      tied(%daemon_dots)->clobber(1);

	  The clobber method is	simply:



									Page 9






PERLTIE(1)							    PERLTIE(1)



	      sub clobber {
		  my $self = shift;
		  $self->{CLOBBER} = @_	? shift	: 1;
	      }


     DELETE this, key
	  This method is triggered when	we remove an element from the hash,
	  typically by using the delete() function.  Again, we'll be careful
	  to check whether they	really want to clobber files.

	      sub DELETE   {
		  carp &whowasi	if $DEBUG;

		  my $self = shift;
		  my $dot = shift;
		  my $file = $self->{HOME} . "/.$dot";
		  croak	"@{[&whowasi]}:	won't remove file $file"
		      unless $self->{CLOBBER};
		  delete $self->{LIST}->{$dot};
		  my $success =	unlink($file);
		  carp "@{[&whowasi]}: can't unlink $file: $!" unless $success;
		  $success;
	      }

	  The value returned by	DELETE becomes the return value	of the call to
	  delete().  If	you want to emulate the	normal behavior	of delete(),
	  you should return whatever FETCH would have returned for this	key.
	  In this example, we have chosen instead to return a value which
	  tells	the caller whether the file was	successfully deleted.

     CLEAR this
	  This method is triggered when	the whole hash is to be	cleared,
	  usually by assigning the empty list to it.

	  In our example, that would remove all	the user's dot files!  It's
	  such a dangerous thing that they'll have to set CLOBBER to something
	  higher than 1	to make	it happen.

	      sub CLEAR	   {
		  carp &whowasi	if $DEBUG;
		  my $self = shift;
		  croak	"@{[&whowasi]}:	won't remove all dot files for $self->{USER}"
		      unless $self->{CLOBBER} >	1;
		  my $dot;
		  foreach $dot ( keys %{$self->{LIST}})	{
		      $self->DELETE($dot);
		  }
	      }






								       Page 10






PERLTIE(1)							    PERLTIE(1)



     EXISTS this, key
	  This method is triggered when	the user uses the exists() function on
	  a particular hash.  In our example, we'll look at the	{LIST} hash
	  element for this:

	      sub EXISTS   {
		  carp &whowasi	if $DEBUG;
		  my $self = shift;
		  my $dot = shift;
		  return exists	$self->{LIST}->{$dot};
	      }


     FIRSTKEY this
	  This method will be triggered	when the user is going to iterate
	  through the hash, such as via	a keys() or each() call.

	      sub FIRSTKEY {
		  carp &whowasi	if $DEBUG;
		  my $self = shift;
		  my $a	= keys %{$self->{LIST}};	  # reset each() iterator
		  each %{$self->{LIST}}
	      }


     NEXTKEY this, lastkey
	  This method gets triggered during a keys() or	each() iteration.  It
	  has a	second argument	which is the last key that had been accessed.
	  This is useful if you're carrying about ordering or calling the
	  iterator from	more than one sequence,	or not really storing things
	  in a hash anywhere.

	  For our example, we're using a real hash so we'll do just the	simple
	  thing, but we'll have	to go through the LIST field indirectly.

	      sub NEXTKEY  {
		  carp &whowasi	if $DEBUG;
		  my $self = shift;
		  return each %{ $self->{LIST} }
	      }


     DESTROY this
	  This method is triggered when	a tied hash is about to	go out of
	  scope.  You don't really need	it unless you're trying	to add
	  debugging or have auxiliary state to clean up.  Here's a very	simple
	  function:

	      sub DESTROY  {
		  carp &whowasi	if $DEBUG;
	      }




								       Page 11






PERLTIE(1)							    PERLTIE(1)



     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:

	 # print out history file offsets
	 use NDBM_File;
	 tie(%HIST, 'NDBM_File', '/usr/lib/news/history', 1, 0);
	 while (($key,$val) = each %HIST) {
	     print $key, ' = ',	unpack('L',$val), "\n";
	 }
	 untie(%HIST);


     Tying FileHandles    [Toc]    [Back]

     This is partially implemented now.

     A class implementing a tied filehandle should define the following
     methods: TIEHANDLE, at least one of PRINT,	PRINTF,	READLINE, GETC,	or
     READ, and possibly	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
     special way. See nvi and the Apache module	for examples.

     In	our example we're going	to create a shouting handle.

	 package Shout;


     TIEHANDLE classname, LIST
	  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.

	      sub TIEHANDLE { print "<shout>\n"; my $i;	bless \$i, shift }


     PRINT this, LIST
	  This method will be triggered	every time the tied handle is printed
	  to with the 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($_),@_)),$\ }


     PRINTF this, LIST
	  This method will be triggered	every time the tied handle is printed
	  to with the printf() function.  Beyond its self reference it also
	  expects the format and list that was passed to the printf function.





								       Page 12






PERLTIE(1)							    PERLTIE(1)



	      sub PRINTF {
		  shift;
		  my $fmt = shift;
		  print	sprintf($fmt, @_)."\n";
	      }


     READ this LIST
	  This method will be called when the handle is	read from via the read
	  or sysread functions.

	      sub READ {
		  $r = shift;
		  my($buf,$len,$offset)	= @_;
		  print	"READ called, \$buf=$buf, \$len=$len, \$offset=$offset";
	      }


     READLINE this
	  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"; }


     GETC this
	  This method will be called when the getc function is called.

	      sub GETC { print "Don't GETC, Get	Perl"; return "a"; }


     DESTROY this
	  As with the other types of ties, this	method will be called when the
	  tied handle is about to be destroyed.	This is	useful for debugging
	  and possibly cleaning	up.

	      sub DESTROY { print "</shout>\n" }


     Here's how	to use our little example:

	 tie(*FOO,'Shout');
	 print FOO "hello\n";
	 $a = 4; $b = 6;
	 print FOO $a, " plus ", $b, " equals ", $a + $b, "\n";
	 print <FOO>;








								       Page 13






PERLTIE(1)							    PERLTIE(1)



     The 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 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;




								       Page 14






PERLTIE(1)							    PERLTIE(1)



	 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 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.



								       Page 15






PERLTIE(1)							    PERLTIE(1)



     In	the second example, however, we	have stored another reference to the
     tied object in $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	-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 -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 before untie() is
     called:

	 undef $x;
	 untie $fred;

SEE ALSO    [Toc]    [Back]

      
      
     See the DB_File manpage or	the Config manpage for some interesting	tie()
     implementations.

BUGS    [Toc]    [Back]

     Tied arrays are incomplete.  They are also	distinctly lacking something
     for the $#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().

     You cannot	easily tie a multilevel	data structure (such as	a hash of
     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 the
     perlmodlib	manpage	for source code	to MLDBM.

AUTHOR    [Toc]    [Back]

     Tom Christiansen

     TIEHANDLE by Sven Verdoolaege <skimo@dns.ufsia.ac.be> and Doug MacEachern
     <dougm@osf.org>










								       Page 16






PERLTIE(1)							    PERLTIE(1)


								       PPPPaaaaggggeeee 11117777
[ Back ]
 Similar pages
Name OS Title
pthread_cond_getname_np Tru64 Obtain the object name from a condition variable object
pthread_cond_setname_np Tru64 Changes the object name in a condition variable object
XmSimpleSpinBox HP-UX a simple SpinBox widget class
CGI IRIX Simple Common Gateway Interface Class
pthread_condattr_init Tru64 Initializes a condition variable attributes object
pthread_condattr_destroy Tru64 Destroys a condition variable attributes object
pthread_condattr_init IRIX initialize/destroy a condition variable attribute object
shred Linux delete a file securely, first overwriting it to hide its contents
pthread_condattr_setpshared Tru64 Change the process-shared attribute of a condition variable attributes object
pthread_condattr_getpshared Tru64 Obtain the process-shared attribute of a condition variable attributes object
Copyright © 2004-2005 DeniX Solutions SRL
newsletter delivery service