- NAME
- SYNOPSIS
- DESCRIPTION
- FUNCTIONS

- GT::Delay

- CAVEATS and LIMITATIONS
- MAINTAINER
- COPYRIGHT
- VERSION

# NAME

GT::Delay - Generic delayed module loading

# SYNOPSIS

        use GT::Delay;

        my $obj = GT::Delay('GT::Foo', 'HASH', foo => "bar", bar => 12);

        ... # time passes without using $obj

        $obj->method();

# DESCRIPTION

This module provides a simple way to handle delayed module loading in a fairly generic way. Your object will only be a very lightweight GT::Delay object until you call a method on it, at which point the desired module will be loaded, your object will be changed into an object of the desired type.

# FUNCTIONS

There is only one usable function provided by this module, GT::Delay() (not GT::Delay::Delay as this module attempts to leave the GT::Delay namespace as empty as possible).

## GT::Delay

GT::Delay is used to create a new delayed object. It takes at least two arguments. The first is the package to load, such as 'GT::Foo' to require GT/Foo.pm and create a new GT::Foo object. The second is the type of blessed data structure a 'GT::Foo' object really is. This can be one of either 'HASH', 'ARRAY', or 'SCALAR'. Any additional arguments are kept and passed in as arguments to the `new()` method of the object when created.

The object type ('HASH', 'ARRAY', or 'SCALAR') is needed is to get around a caveat of references - if $a and $b both point to the same reference, $b cannot be changed from $a - which makes it impossible to just get a new object and replace $_[0] with that object, because although that would change one of either $a or $b, it wouldn't change the other and you could easily end up with two separate objects. When a method is called, the new object is created, then copied into the original object which is then reblessed into the desired package. This doesn't change either $a or $b, but rather changes the reference they point to. You have to pass the object type because the reference must be reblessed, but the underlying data type cannot change. Unfortunately, this approach has a few caveats of its own, listed below.

# CAVEATS and LIMITATIONS

Modules that are created by a method other than `new()` are not supported.

Modules that use a namespace different from the module location are not supported. For example, a package Foo::Bar::Blah located in Foo/Bar.pm. If you have such a module that would benefit from delayed loading, you need to rethink your package/filename naming scheme, or not use this module. It _is_ possible to do this with a hack such as: `$INC{'Foo/Bar/Blah.pm'} = './Foo/Bar.pm';` - but other than for testing, doing such a thing is strongly discouraged.

Objects cannot have their elements directly accessed - for example, `$obj->{foo}`. But, since that is bad practise anyway, it isn't that much of a limitation. That said, objects _can_ be accessed directly _after_ any method has been called.

Modules that store a string or integer form of $self (GT::Config does this to store object attributes) will not work, since the working object will not be the same object create a new(), but rather a copy.

Modules with DESTROY methods that do things to references in $self (for example, `delete $self->{foo}->{bar}` - though `delete $self-E<gt>{foo}` would be safe) will most likely not work properly as the copy is not deep - i.e. references are copied as-is.

Along the same lines as the previous point, the first object will be destroyed before the first method call goes through, so modules that do things (e.g. delete files, close filehandles, etc.) in DESTROY will most likely not work.

Any module that doesn't fall into any of the points above will be perfectly well supported by this module.

# MAINTAINER

Jason Rhinelander

# COPYRIGHT

Copyright (c) 2004 Gossamer Threads Inc. All Rights Reserved. http://www.gossamer-threads.com/

# VERSION

Revision: $Id: Delay.pm,v 1.4 2004/01/13 01:35:15 jagerman Exp $