tadman has asked for the wisdom of the Perl Monks concerning the following question:

Is there a quick way to find the reference count for a particular scalar? Preferably using internal modules.

The intention is to make a cache that can expire references that are no longer used, which would be indicated by the reference count being 1, not zero, since the cache itself is a reference. These would be purged whenever required.

Replies are listed 'Best First'.
Re: Reference Count
by chromatic (Archbishop) on Nov 19, 2002 at 21:26 UTC

    Offhand, I'm not sure of finding this from pure Perl, though it's theoretically very easy from XS. You might try weak references in 5.6.0 and later, though (see Scalar::Util). Otherwise, matts has a good article on Proxy Objects that can solve this problem.

    I'd probably use weak references, if I were you.

      The "weak" references from Scalar::Util are a great thing to know about. I was trying to create a reference that wasn't counted, and that's exactly what the weaken() function does.

      The only problem is that during processing, variables may fall out of scope and get undefined before their time is up. That's the reason I was trying to construct a cache. The cost of constructing an object is expensive enough (RDBMS) that keeping it around for a while is a good idea, even if it has temporarily fallen out of use.

      mojotoad does have a point. This is precisely what Perl does with its own garbage collection routines. I don't intend to replace this for everything, just delay it for those objects which need to be preserved.

      It isn't always practical to pass around all the data you need from function to function, especially if they are unrelated. The cache will serve to link together records that are not explicitly linked, but implicitly, something that isn't always clear in advance.

      What I'm really trying to do is load any given DB row once, and work with it until it "expires", which is usually at the end of the transaction, though for some pseudo-static data, this could be considerably longer. Perl treats all objects as being equal, and discards them when it gets around to it. I'm looking for some degree of control over the process.

      Having a refrerence count isn't vital, but sure would come in handy when trying to prune the cache.
        Weak references are still what I would recommend.

        You want a double data structure. One cache with weak references which you use when accessing possibly cached objects. And one data structure to keep references to objects that you want to keep from expiring. Flush the second one as appropriate, access through the first. Perl's GC does everything else for you.

Re: Reference Count
by Elian (Parson) on Nov 19, 2002 at 22:22 UTC
    If that's what you want to do, and you don't mind scanning the cache periodically (otherwise weak references are probably the way to do) then use Devel::Peek to peek. The SvREFCNT function will get you the refcount for any perl variable.
Re: Reference Count
by mojotoad (Monsignor) on Nov 19, 2002 at 21:27 UTC
    I'm compelled to ask. This sounds precisely like the functionality of Perl's internal garbage collection. Is the native garbage collection not sufficient for your purposes, or do you really need the reference count for some other use?

    Matt

Re: Reference Count
by diotalevi (Canon) on Nov 22, 2002 at 22:37 UTC

    I'm amazed that no one else mentioned the B module to you. All your scalar references will return the REFCNT number from the referenced scalar. I provided an example - this is a dirt easy task.

    use B 'svref_2object'; my $something = "this is tadman's cached data"; my $something_obj = svref_2object(\$something); my $something_refcnt = $something_obj->REFCNT;
    __SIG__ use B; printf "You are here %08x\n", unpack "L!", unpack "P4", pack "L!", B::svref_2object(sub{})->OUTSIDE;