http://qs321.pair.com?node_id=30545


in reply to (Guildenstern) REx2: Win32::MemoryInfo
in thread Win32::MemoryInfo

I'll start from the beginning because I don't think I'll make much sense otherwise.

Okay, the basic idea is that, with so many values being returned (3 is usually too many in my book), remembering the exact order of the values is problematic. Also, if you are returning a whole list of things, it'd be nice to design the interface so it can evolve in an intelligent manner.

So, just like when you have lots of parameters, it is nice to "name" them (func(This=>"that",Count=>2)), you can return "named" values by returning a hash. I try to avoid returning hashes as lists so let's return a reference to a hash.

One of the nice things about named parameters is that you can leave out any parameters that you aren't interested in. So let's allow the user the same option here. If they only want page file information in megabytes, they can write:

my( $avail, $total )= MemoryStatus( "MB", "AvailPageFile", "TotalPageFile" );

The "MB" parameter is optional and we can detect it due to it being different from any of the field names. If you think you may further extend the interface in the future, you might want to make this distinction clearer and allow for extra arguments by having the field names passed as an array reference:

my( $avail, $total )= MemoryStatus( "MB", [ "AvailPageFile", "TotalPageFile" ] );
but I don't think that is warranted in this case.

If the user wants all or most of the items, then they use it like this:

my $hMem= MemoryStatus( "K" ); my $load= $hMem->{MemoryLoad};

This is particularly handy for add-hoc queries in the Perl debugger:

perl -de 0 DB<1> use Win32::MemoryInfo "MemoryStatus" DB<2> x MemoryStatus() 0 HASH(0x1df2628) 'AvailPageFile' => 3026 'TotalPageFile' => 32768 [...]

And Perl makes this easy to code as well:

my @fieldNames= qw( MemoryLoad TotalPhys AvailPhys TotalPageFile AvailPageFile TotalVirtual AvailVirtual ); my %unitSize= ( B=>1, K=>1024, M=>1024*1024, G=>1024*1024*1024 ); #[...] my( $sUnits )= "B"; if( @_ && $_[0] =~ /^[BKMG]B?$/i ) { $sUnits= uc substr(shift(@_),0,1); } my( $nUnits )= $unitSize{$sUnits}; my( $dwMSLength )= 0; my( @fieldValues )= (0)x@fieldNames; my $MEMORYSTATUS= pack "L8", $dwMSLength, @fieldValues; $GlobalMemoryStatus->Call($MEMORYSTATUS); ( $dwMSLength, @fieldValues )= unpack "L8", $MEMORYSTATUS; return if 0 == $dwMSLength; for( @fieldValues ) { $_ /= $nUnits; } my $hFields= {}; @$hFields{@fieldNames}= @fieldValues; return @_ ? @$hFields{@_} : $hFields;
        - tye (but my friends call me "Tye")