Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change

RE: RE: RE: Win32::MemoryInfo

by tye (Sage)
on Aug 31, 2000 at 19:24 UTC ( #30545=note: print w/replies, xml ) Need Help??

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")

Replies are listed 'Best First'.
(Guildenstern ) REx4: Win32::MemoryInfo
by Guildenstern (Deacon) on Aug 31, 2000 at 20:02 UTC
    Okay. I see what you're saying about the parameters now. I was thinking of doing something like this:
    my %meminfo = { TotalPhys=>0, AvailPhys=>0 }; MemoryStatus(\%meminfo,"KB");

    but it seemed like too much work to make the user do, and setting hash values to 0 might be confusing. It would lessen the task of checking the parameter list, though, and we still have a hash reference which I agree is better than returning a specifically ordered list. Maybe I can include both options?

    Negaterd character class uber alles!
      Silly trick:
      my %args = %default, @_; foreach my $arg (keys %args) { unless (exists $allowed{$arg}) { croak("Unrecognized argument '$arg' passed to MemoryStatus."); } }
      Just put all possible defaults in %default and the user can override any combination they want, and your %allowed check will catch most typos and misunderstandings of the API.

RE: (Guildenstern: TMTOWTDI): Win32::MemoryInfo
by Guildenstern (Deacon) on Sep 01, 2000 at 00:48 UTC
    Here's what I came up with after some reworking. I decided to go with a hash reference as the main parameter instead of taking words. This also means that it must now be called like this:
    my %hMem = (TotalPhys =>0, AvailPhys =>0); Win32::MemoryInfo::MemoryStatus(%hMem,"MB");

    I don't know what the consensus is on putting values into a hash like that, but if someone doesn't check the return value at least they won't get bit with undef values.
    Here's the reworked function:
    sub MemoryStatus (\%;$) { my $return = shift; my $ret_type = shift; my %fmt_types = ( B => 1, KB => 1024, MB => 1024*1024, GB => 1024*1024*1024); my @params = qw(MemLoad TotalPhys AvailPhys TotalPage AvailPage TotalVirtual AvailVirtual); my %results; my $MemFormat; my $dwMSLength; $MemFormat = ($ret_type =~ /^[BKMG]B?$/) ? $fmt_types{$ret_type} : $fmt_types{B} +; my $GlobalMemoryStatus ||= new Win32::API("kernel32", "GlobalMemoryStatus", ["P"], "V") or ret +urn undef; my $MEMORYSTATUS = pack "L8",(0, 0, 0, 0, 0, 0, 0, 0); $GlobalMemoryStatus->Call($MEMORYSTATUS); ($dwMSLength, @results{@params}) = unpack "L8", $MEMORYSTATUS; return undef if ($dwMSLength == 0); if (keys(%$return) == 0) { foreach (@params) { $return->{$_} = ($_ eq "MemLoad") ? $results{$_} : $results{$_}/$M +emFormat; } } else { foreach (@params){ $return->{$_} = $results{$_}/$MemFormat unless (!defined($return- +>{$_})); } } 1; }

    Negaterd character class uber alles!

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://30545]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (5)
As of 2017-07-22 08:57 GMT
Find Nodes?
    Voting Booth?
    I came, I saw, I ...

    Results (337 votes). Check out past polls.