| 1 | =head1 NAME
|
|---|
| 2 | X<tie>
|
|---|
| 3 |
|
|---|
| 4 | perltie - how to hide an object class in a simple variable
|
|---|
| 5 |
|
|---|
| 6 | =head1 SYNOPSIS
|
|---|
| 7 |
|
|---|
| 8 | tie VARIABLE, CLASSNAME, LIST
|
|---|
| 9 |
|
|---|
| 10 | $object = tied VARIABLE
|
|---|
| 11 |
|
|---|
| 12 | untie VARIABLE
|
|---|
| 13 |
|
|---|
| 14 | =head1 DESCRIPTION
|
|---|
| 15 |
|
|---|
| 16 | Prior to release 5.0 of Perl, a programmer could use dbmopen()
|
|---|
| 17 | to connect an on-disk database in the standard Unix dbm(3x)
|
|---|
| 18 | format magically to a %HASH in their program. However, their Perl was either
|
|---|
| 19 | built with one particular dbm library or another, but not both, and
|
|---|
| 20 | you couldn't extend this mechanism to other packages or types of variables.
|
|---|
| 21 |
|
|---|
| 22 | Now you can.
|
|---|
| 23 |
|
|---|
| 24 | The tie() function binds a variable to a class (package) that will provide
|
|---|
| 25 | the implementation for access methods for that variable. Once this magic
|
|---|
| 26 | has been performed, accessing a tied variable automatically triggers
|
|---|
| 27 | method calls in the proper class. The complexity of the class is
|
|---|
| 28 | hidden behind magic methods calls. The method names are in ALL CAPS,
|
|---|
| 29 | which is a convention that Perl uses to indicate that they're called
|
|---|
| 30 | implicitly rather than explicitly--just like the BEGIN() and END()
|
|---|
| 31 | functions.
|
|---|
| 32 |
|
|---|
| 33 | In the tie() call, C<VARIABLE> is the name of the variable to be
|
|---|
| 34 | enchanted. C<CLASSNAME> is the name of a class implementing objects of
|
|---|
| 35 | the correct type. Any additional arguments in the C<LIST> are passed to
|
|---|
| 36 | the appropriate constructor method for that class--meaning TIESCALAR(),
|
|---|
| 37 | TIEARRAY(), TIEHASH(), or TIEHANDLE(). (Typically these are arguments
|
|---|
| 38 | such as might be passed to the dbminit() function of C.) The object
|
|---|
| 39 | returned by the "new" method is also returned by the tie() function,
|
|---|
| 40 | which would be useful if you wanted to access other methods in
|
|---|
| 41 | C<CLASSNAME>. (You don't actually have to return a reference to a right
|
|---|
| 42 | "type" (e.g., HASH or C<CLASSNAME>) so long as it's a properly blessed
|
|---|
| 43 | object.) You can also retrieve a reference to the underlying object
|
|---|
| 44 | using the tied() function.
|
|---|
| 45 |
|
|---|
| 46 | Unlike dbmopen(), the tie() function will not C<use> or C<require> a module
|
|---|
| 47 | for you--you need to do that explicitly yourself.
|
|---|
| 48 |
|
|---|
| 49 | =head2 Tying Scalars
|
|---|
| 50 | X<scalar, tying>
|
|---|
| 51 |
|
|---|
| 52 | A class implementing a tied scalar should define the following methods:
|
|---|
| 53 | TIESCALAR, FETCH, STORE, and possibly UNTIE and/or DESTROY.
|
|---|
| 54 |
|
|---|
| 55 | Let's look at each in turn, using as an example a tie class for
|
|---|
| 56 | scalars that allows the user to do something like:
|
|---|
| 57 |
|
|---|
| 58 | tie $his_speed, 'Nice', getppid();
|
|---|
| 59 | tie $my_speed, 'Nice', $$;
|
|---|
| 60 |
|
|---|
| 61 | And now whenever either of those variables is accessed, its current
|
|---|
| 62 | system priority is retrieved and returned. If those variables are set,
|
|---|
| 63 | then the process's priority is changed!
|
|---|
| 64 |
|
|---|
| 65 | We'll use Jarkko Hietaniemi <F<[email protected]>>'s BSD::Resource class (not
|
|---|
| 66 | included) to access the PRIO_PROCESS, PRIO_MIN, and PRIO_MAX constants
|
|---|
| 67 | from your system, as well as the getpriority() and setpriority() system
|
|---|
| 68 | calls. Here's the preamble of the class.
|
|---|
| 69 |
|
|---|
| 70 | package Nice;
|
|---|
| 71 | use Carp;
|
|---|
| 72 | use BSD::Resource;
|
|---|
| 73 | use strict;
|
|---|
| 74 | $Nice::DEBUG = 0 unless defined $Nice::DEBUG;
|
|---|
| 75 |
|
|---|
| 76 | =over 4
|
|---|
| 77 |
|
|---|
| 78 | =item TIESCALAR classname, LIST
|
|---|
| 79 | X<TIESCALAR>
|
|---|
| 80 |
|
|---|
| 81 | This is the constructor for the class. That means it is
|
|---|
| 82 | expected to return a blessed reference to a new scalar
|
|---|
| 83 | (probably anonymous) that it's creating. For example:
|
|---|
| 84 |
|
|---|
| 85 | sub TIESCALAR {
|
|---|
| 86 | my $class = shift;
|
|---|
| 87 | my $pid = shift || $$; # 0 means me
|
|---|
| 88 |
|
|---|
| 89 | if ($pid !~ /^\d+$/) {
|
|---|
| 90 | carp "Nice::Tie::Scalar got non-numeric pid $pid" if $^W;
|
|---|
| 91 | return undef;
|
|---|
| 92 | }
|
|---|
| 93 |
|
|---|
| 94 | unless (kill 0, $pid) { # EPERM or ERSCH, no doubt
|
|---|
| 95 | carp "Nice::Tie::Scalar got bad pid $pid: $!" if $^W;
|
|---|
| 96 | return undef;
|
|---|
| 97 | }
|
|---|
| 98 |
|
|---|
| 99 | return bless \$pid, $class;
|
|---|
| 100 | }
|
|---|
| 101 |
|
|---|
| 102 | This tie class has chosen to return an error rather than raising an
|
|---|
| 103 | exception if its constructor should fail. While this is how dbmopen() works,
|
|---|
| 104 | other classes may well not wish to be so forgiving. It checks the global
|
|---|
| 105 | variable C<$^W> to see whether to emit a bit of noise anyway.
|
|---|
| 106 |
|
|---|
| 107 | =item FETCH this
|
|---|
| 108 | X<FETCH>
|
|---|
| 109 |
|
|---|
| 110 | This method will be triggered every time the tied variable is accessed
|
|---|
| 111 | (read). It takes no arguments beyond its self reference, which is the
|
|---|
| 112 | object representing the scalar we're dealing with. Because in this case
|
|---|
| 113 | we're using just a SCALAR ref for the tied scalar object, a simple $$self
|
|---|
| 114 | allows the method to get at the real value stored there. In our example
|
|---|
| 115 | below, that real value is the process ID to which we've tied our variable.
|
|---|
| 116 |
|
|---|
| 117 | sub FETCH {
|
|---|
| 118 | my $self = shift;
|
|---|
| 119 | confess "wrong type" unless ref $self;
|
|---|
| 120 | croak "usage error" if @_;
|
|---|
| 121 | my $nicety;
|
|---|
| 122 | local($!) = 0;
|
|---|
| 123 | $nicety = getpriority(PRIO_PROCESS, $$self);
|
|---|
| 124 | if ($!) { croak "getpriority failed: $!" }
|
|---|
| 125 | return $nicety;
|
|---|
| 126 | }
|
|---|
| 127 |
|
|---|
| 128 | This time we've decided to blow up (raise an exception) if the renice
|
|---|
| 129 | fails--there's no place for us to return an error otherwise, and it's
|
|---|
| 130 | probably the right thing to do.
|
|---|
| 131 |
|
|---|
| 132 | =item STORE this, value
|
|---|
| 133 | X<STORE>
|
|---|
| 134 |
|
|---|
| 135 | This method will be triggered every time the tied variable is set
|
|---|
| 136 | (assigned). Beyond its self reference, it also expects one (and only one)
|
|---|
| 137 | argument--the new value the user is trying to assign. Don't worry about
|
|---|
| 138 | returning a value from STORE -- the semantic of assignment returning the
|
|---|
| 139 | assigned value is implemented with FETCH.
|
|---|
| 140 |
|
|---|
| 141 | sub STORE {
|
|---|
| 142 | my $self = shift;
|
|---|
| 143 | confess "wrong type" unless ref $self;
|
|---|
| 144 | my $new_nicety = shift;
|
|---|
| 145 | croak "usage error" if @_;
|
|---|
| 146 |
|
|---|
| 147 | if ($new_nicety < PRIO_MIN) {
|
|---|
| 148 | carp sprintf
|
|---|
| 149 | "WARNING: priority %d less than minimum system priority %d",
|
|---|
| 150 | $new_nicety, PRIO_MIN if $^W;
|
|---|
| 151 | $new_nicety = PRIO_MIN;
|
|---|
| 152 | }
|
|---|
| 153 |
|
|---|
| 154 | if ($new_nicety > PRIO_MAX) {
|
|---|
| 155 | carp sprintf
|
|---|
| 156 | "WARNING: priority %d greater than maximum system priority %d",
|
|---|
| 157 | $new_nicety, PRIO_MAX if $^W;
|
|---|
| 158 | $new_nicety = PRIO_MAX;
|
|---|
| 159 | }
|
|---|
| 160 |
|
|---|
| 161 | unless (defined setpriority(PRIO_PROCESS, $$self, $new_nicety)) {
|
|---|
| 162 | confess "setpriority failed: $!";
|
|---|
| 163 | }
|
|---|
| 164 | }
|
|---|
| 165 |
|
|---|
| 166 | =item UNTIE this
|
|---|
| 167 | X<UNTIE>
|
|---|
| 168 |
|
|---|
| 169 | This method will be triggered when the C<untie> occurs. This can be useful
|
|---|
| 170 | if the class needs to know when no further calls will be made. (Except DESTROY
|
|---|
| 171 | of course.) See L<The C<untie> Gotcha> below for more details.
|
|---|
| 172 |
|
|---|
| 173 | =item DESTROY this
|
|---|
| 174 | X<DESTROY>
|
|---|
| 175 |
|
|---|
| 176 | This method will be triggered when the tied variable needs to be destructed.
|
|---|
| 177 | As with other object classes, such a method is seldom necessary, because Perl
|
|---|
| 178 | deallocates its moribund object's memory for you automatically--this isn't
|
|---|
| 179 | C++, you know. We'll use a DESTROY method here for debugging purposes only.
|
|---|
| 180 |
|
|---|
| 181 | sub DESTROY {
|
|---|
|
|---|