in reply to Re: Re: Win32::MMF - Memory Mapped File Support for Perl
in thread (Updated Again) Win32::MMF - Memory Mapped File Support for Perl
General interface
IPC::Shareable has the following basic interface:
where you can do a simple 3-arg tie() and that's all, or optionally pass a hashref of options. Could i suggest a similar interface for Win32::MMF::Shareable:use IPC::Shareable; # simple method tie( $scalar, 'IPC::Shareable', 'varid' ); # complex method tie( $scalar, 'IPC::Shareable', 'varid', { ...options... } ); # OR tie( $scalar, 'IPC::Shareable', { key => 'varid', ...options... } );
Rather than having to call Win32::MMF::Shareable::Init to set things like namespace (see following section), size, autolock, etc, use defaults for everything and pass a hashref of option overrides to tie(). To avoid having to set the same options for each tie call every time, change Init() to setdefaults() so it works something like this:use Win32::MMF::Shareable; # simple method tie( $scalar, 'Win32::MMF::Shareable', 'varid' ); # automatically creates a namespace using default options # complex method tie( $scalar, 'Win32::MMF::Shareable', 'varid', { ...options... } ); +# OR tie( $scalar, 'Win32::MMF::Shareable', { key => 'varid', ...options... + } ); # for compatibility
If you tie without any options you get the default values for each option. Optionally, you can call Win32::MMF::Shareable->setdefaults() to change the defaults for any future calls to tie. This way you have the best of simplicity and flexibility.use Win32::MMF::Shareable; # BAD tie( $bigvar1, 'Win32::MMF::Shareable', 'bigvar1', { autolock => 0, si +ze => 1024 ** 2 } ); tie( $bigvar2, 'Win32::MMF::Shareable', 'bigvar2', { autolock => 0, si +ze => 1024 ** 2 } ); tie( $bigvar3, 'Win32::MMF::Shareable', 'bigvar3', { autolock => 0, si +ze => 1024 ** 2 } ); # GOOD Win32::MMF::Shareable->setdefaults( { autolock => 0, size => 1024 ** 2 + } ); tie( $bigvar1, 'Win32::MMF::Shareable', 'bigvar1' ); tie( $bigvar2, 'Win32::MMF::Shareable', 'bigvar2' ); tie( $bigvar3, 'Win32::MMF::Shareable', 'bigvar3' );
Thoughts on namespaces
IPC::Shareable uses a single identifier to reference a shared variable (refereed to as GLUE or key in the docs), where as Win32::MMF has two levels, a namespace and an identifier within the namespace. While this works well in Win32::MMF, as the namespace can be the object and you can have multiple items within the namespace, it becomes somewhat redundant when you tie a single variable with Win32::MMF::Shareable.
My suggestion would be to make the namespace option in Win32::MMF::Shareable optional, and have it transparently create and use the default namespace 'shareable'. This eliminates redundancy, still allows the user to override it if necessary, and allows users to mix-n-match the two modules:tie( $scalar, 'Win32::MMF::Shareable', { namespace => 'ns1', key => 'f +oo' } ); tie( $scalar, 'Win32::MMF::Shareable', { namespace => 'ns1', key => 'b +ar' } ); tie( $scalar, 'Win32::MMF::Shareable', { namespace => 'ns2', key => 'f +oo' } ); tie( $scalar, 'Win32::MMF::Shareable', { namespace => 'ns2', key => 'b +ar' } );
Options# Process 1 use Win32::MMF::Shareable; my @queue; tie( @queue, 'Win32::MMF::Shareable', 'queue' ); @queue = qw( 8265 6201 7548 2165 7892 3546 3426 6246 ); # Process 2 use Win32::MMF; my $ns = Win32::MMF->new( -namespace => "my_namespace" ); $ns->setvar( fredsname => 'fred' ); my $fredsname = $ns->getvar( 'fredsname' ); # etc... as normal # get the current value of another processes tied variable! my $server = Win32::MMF->new( -namespace => "shareable", reuse => 1 ); + my @current_queue = $server->getvar( 'queue' );
The two modules use different flags to control when a particular 'varid' is created or mapped to an existing one. IPC::Shareable uses create & exclusive flags, while Win32::MMF has a single reuse flag, and they behave as follows (bold is the default):
IPC::Shareable
create flag | exclusive flag | varid doesn't exist | varid already exists |
0 | (unused) | croaks | maps to varid |
1 | 0 | creates new varid | maps to varid |
1 | 1 | creates new varid | croaks |
Win32::MMF
reuse flag | varid doesn't exist | varid already exists |
0 | creates new varid | maps to varid |
1 | fails silently | maps to varid |
Currently you can't specify for Win32::MMF to create exclusively failing if the varid already exists. How about something like the following, which handles all 3 cases simply:
connect flag | varid doesn't exist | varid already exists |
undef (or "auto"?) | creates new varid | maps to varid |
1 | fails silently | maps to varid |
0 | creates new varid | fails silently |
To maintain compatibility with IPC::Shareable you would still need to accept 'create' and 'exclusive' flags (but overridden by 'connect' if present) and convert them to the appropriate connect flag.tie( $var, 'Win32::MMF::Shareable', 'var' ); # OR tie( $var, 'Win32::MMF::Shareable', 'var', { connect => 'auto' } ); # + map if already available, otherwise create tie( $var, 'Win32::MMF::Shareable', 'var', { connect => 1 } ); # must +already exist tie( $var, 'Win32::MMF::Shareable', 'var', { connect => 0 } ); # must +not already exist
The other IPC::Shareable options are:
Tied object
Now that we tie our shared variable, we no longer have access to an object which means we lose functionality of lock(), unlock(), debug(), and anything else you decide to implement in the future. Other tie() modules overcome this by returning an object from the call to tie(), which would allow things like:
$data = tie( %data, 'Win32::MMF::Shareable', 'data', { timeout => 60 } + ); if( $data->{error} ) { die( can't tie data: . $data->{errstr} ) } +# maybe? or just return undef $data{min} = 0; $data{max} = 500; $data{current} = 0; $data->debug() if $debug_flag; # each process must do blocks of 10 at a time { $data->lock(); # timeout 60 seconds for( $data{end} = $data{current} + 10; $data{current} < $data{end}; +$data{current}++ ) { # do job number $data{current} } $data->unlock(); }
Other thoughts
*phew* I thinks that's about it... feedback welcome!
- ><iper
use japh; print;