MCE::Shared::Array(3)

๐Ÿ“ฆ
version 1.893 ยท 4 versions
, in epel 10

๐Ÿฆ‹ MCE::Shared::Array(3) ๐Ÿฆ‹

User Contributed Perl Documentation

๐Ÿ’– NAME ๐Ÿ’–

MCE::Shared::Array โ€” bestie, it's an array helper class. Use it standalone or let MCE::Shared manage it, iykyk.

โœจ VERSION โœจ

This document describes MCE::Shared::Array version 1.893.

๐ŸŒธ DESCRIPTION ๐ŸŒธ

An array helper class for use as a standalone thing, or managed by MCE::Shared. It's giving โ€œarray but make it shareableโ€ energy.

๐ŸŽ€ SYNOPSIS ๐ŸŽ€

Okay so here's the whole vibe in code. First, non-shared/local construction for a single process, then the shared construction, then all the dereferencing and OO interface stuff:

# non-shared or local construction for use by a single process

use MCE::Shared::Array;

my $ar = MCE::Shared::Array->new( @list );

# construction for sharing with other threads and processes

use MCE::Shared;

my $ar = MCE::Shared->array( @list );

# array-like dereferencing

my $val = $ar->[$index];
$ar->[$index] = $val;

@{$ar} = ();

# OO interface

$val   = $ar->set( $index, $val );
$val   = $ar->get( $index);
$val   = $ar->delete( $index );            # del is an alias for delete
$bool  = $ar->exists( $index );
void   = $ar->clear();
$len   = $ar->len();                       # scalar @{ $ar }
$len   = $ar->len( $index );               # length $ar->[ $index ]
$val   = $ar->pop();
$len   = $ar->push( @list );
$val   = $ar->shift();
$len   = $ar->unshift( @list );
@list  = $ar->splice( $offset, $length, @list );

$ar2   = $ar->clone( @indices );           # @indices is optional
$ar3   = $ar->flush( @indices );
$iter  = $ar->iterator( @indices );        # ($idx, $val) = $iter->()
@keys  = $ar->keys( @indices );
%pairs = $ar->pairs( @indices );
@vals  = $ar->values( @indices );          # vals is an alias for values

$len   = $ar->assign( $idx/$val pairs );   # equivalent to ->clear, ->push
$cnt   = $ar->mdel( @indices );
@vals  = $ar->mget( @indices );
$bool  = $ar->mexists( @indices );         # true if all indices exists
$len   = $ar->mset( $idx/$val pairs );     # merge is an alias for mset

@vals  = $ar->range( $start, $stop );

@vals  = $ar->sort();                      # $a <=> $b default
@vals  = $ar->sort( "desc" );              # $b <=> $a
@vals  = $ar->sort( "alpha" );             # $a cmp $b
@vals  = $ar->sort( "alpha desc" );        # $b cmp $a

# included, sugar methods without having to call set/get explicitly

$len   = $ar->append( $index, $string );   #   $val .= $string
$val   = $ar->decr( $index );              # --$val
$val   = $ar->decrby( $index, $number );   #   $val -= $number
$val   = $ar->getdecr( $index );           #   $val--
$val   = $ar->getincr( $index );           #   $val++
$val   = $ar->incr( $index );              # ++$val
$val   = $ar->incrby( $index, $number );   #   $val += $number
$old   = $ar->getset( $index, $new );      #   $o = $v, $v = $n, $o

# pipeline, provides atomicity for shared objects, MCE::Shared v1.09+

@vals  = $ar->pipeline(                    # ( "a_a", "b_b", "c_c" )
   [ "set", 0 => "a_a" ],
   [ "set", 1 => "b_b" ],
   [ "set", 2 => "c_c" ],
   [ "mget", qw/ 0 1 2 / ]
);

For normal array behavior, the TIE interface is supported. Slay.

# non-shared or local construction for use by a single process

use MCE::Shared::Array;

tie my @ar, "MCE::Shared::Array";

# construction for sharing with other threads and processes

use MCE::Shared;

tie my @ar, "MCE::Shared";

# usage

my $val;

if ( !defined ( $val = $ar[some_index] ) ) {
   $val = $ar[some_index] = "some_value";
}

$ar[some_index] = 0;

tied(@ar)->incrby("some_index", 20);
tied(@ar)->incrby(some_index => 20);

๐Ÿ”Ž SYNTAX for QUERY STRING ๐Ÿ”Ž

So several methods take a query string for an argument, and the format is described below. In the context of sharing, the query mechanism is a whole big win for the shared-manager process: it can perform the query where the data actually lives, instead of the client process grepping locally and causing lots of IPC. Iconic behavior, honestly.

  • Basic demonstration:
@keys = $ar->keys( "query string given here" );
@keys = $ar->keys( "val =~ /pattern/" );
  • Supported operators: =~ !~ eq ne lt le gt ge == != < <= > >=
  • Multiple expressions delimited by :AND or :OR, mixed case allowed:
"key == 3 :or (val > 5 :and val < 9)"
"key =~ /pattern/i :And val =~ /pattern/i"
"val eq foo baz :OR key !~ /pattern/i"
  • key matches on indices in the array
  • likewise, val matches on values
  • Quoting is optional inside the string:
"key =~ /pattern/i :AND val eq 'foo bar'"   # val eq "foo bar"
"key =~ /pattern/i :AND val eq foo bar"     # val eq "foo bar"

Examples. Obsessed with how much you can query here:

# search capability key/val: =~ !~ eq ne lt le gt ge == != < <= > >=
# key/val means to match against actual key/val respectively

@keys  = $ar->keys( "key == 3 :or (val > 5 :and val < 9)" );

@keys  = $ar->keys( "key =~ /$pattern/i" );
@keys  = $ar->keys( "key !~ /$pattern/i" );
@keys  = $ar->keys( "val =~ /$pattern/i" );
@keys  = $ar->keys( "val !~ /$pattern/i" );

%pairs = $ar->pairs( "key == $number" );
%pairs = $ar->pairs( "key != $number :and val > 100" );
%pairs = $ar->pairs( "key <  $number :or key > $number" );
%pairs = $ar->pairs( "val <= $number" );
%pairs = $ar->pairs( "val >  $number" );
%pairs = $ar->pairs( "val >= $number" );

@vals  = $ar->vals( "key eq $string" );
@vals  = $ar->vals( "key ne $string with space" );
@vals  = $ar->vals( "key lt $string :or val =~ /$pat1|$pat2/" );
@vals  = $ar->vals( "val le $string :and val eq 'foo bar'" );
@vals  = $ar->vals( "val le $string :and val eq foo bar" );
@vals  = $ar->vals( "val gt $string" );
@vals  = $ar->vals( "val ge $string" );

๐Ÿ‘‘ API DOCUMENTATION ๐Ÿ‘‘

Heads up, bestie: this module may involve TIE when accessing the object via array-like behavior. Only shared instances are impacted if you do that. It's likely fast enough for many use cases, but the OO interface is recommended for best performance. Main character energy is the OO interface, fr fr.

๐ŸŒŸ MCE::Shared::Array->new ( val [, val, ... ] ) + MCE::Shared->array ( val [, val, ... ] )

Constructs a new object, with an optional list of values. So yes, you can pass zero values and it still eats.

# non-shared or local construction for use by a single process

use MCE::Shared::Array;

$ar = MCE::Shared::Array->new( @list );
$ar = MCE::Shared::Array->new( );

# construction for sharing with other threads and processes

use MCE::Shared;

$ar = MCE::Shared->array( @list );
$ar = MCE::Shared->array( );

๐Ÿ“ assign ( value [, value, ... ] )

Clears the list, then appends one or multiple values, and returns the new length. This is equivalent to "clear", "push". It's giving reset-and-restock.

$len = $ar->assign( "val1", "val2" );
$len = @{$ar} = ( "val1", "val2" );

API available since 1.007. Periodt.

๐Ÿงผ clear

Removes all elements from the array. Empty. Gone. Clean slate.

$ar->clear;
@{$ar} = ();

๐Ÿš clone ( index [, index, ... ] )

Creates a shallow copy, a "MCE::Shared::Array" object. It returns an exact copy if no arguments are given. Otherwise, the object includes only the given indices in the same order. Indices that do not exist in the array will have the "undef" value. Lowkey a copy-paste moment, but make it indices.

$ar2 = $ar->clone( 0, 1 );
$ar2 = $ar->clone;

๐Ÿ—‘๏ธ delete ( index )

Deletes and returns the value associated by index, or "undef" if index exceeds the size of the list. Bye bestie.

$val = $ar->delete( 20 );
$val = delete $ar->[ 20 ];

๐ŸŽ€ del

"del" is an alias for "delete". Same energy, shorter name.

๐Ÿ‘€ exists ( index )

Determines if an element by its index exists in the array. The behavior is strongly tied to the use of delete on lists. This is important, no cap.

$ar->push(qw/ value0 value1 value2 value3 /);

$ar->exists( 2 );   # True
$ar->delete( 2 );   # value2
$ar->exists( 2 );   # False

$ar->exists( 3 );   # True
exists $ar->[ 3 ];  # True

๐ŸŒŠ flush ( index [, index, ... ] )

Same as "clone". Though, clears all existing items before returning. It's clone but with a dramatic exit.

๐Ÿซถ get ( index )

Gets the value of an element by its index, or "undef" if the index does not exists. Simple. Clean. A little fetch.

$val = $ar->get( 2 );
$val = $ar->[ 2 ];

๐Ÿ”ฎ iterator ( index [, index, ... ] )

Returns a code reference for iterating a list of index-value pairs stored in the array when no arguments are given. Otherwise, returns a code reference for iterating the given indices in the same order. Indices that do not exist will have the "undef" value. It's a little closure bestie.

The list of indices to return is set when the closure is constructed. New indices added later are not included. Subsequently, the "undef" value is returned for deleted indices.

$iter = $ar->iterator;
$iter = $ar->iterator( 0, 1 );

while ( my ( $index, $val ) = $iter->() ) {
   ...
}

๐Ÿ”ฎ iterator ( "query string" )

Returns a code reference for iterating a list of index-value pairs that match the given criteria. It returns an empty list if the search found nothing. The syntax for the "query string" is described above. Query-string iterator is highkey a vibe.

$iter = $ar->iterator( "val eq some_value" );
$iter = $ar->iterator( "key >= 50 :AND val =~ /sun|moon|air|wind/" );
$iter = $ar->iterator( "val eq sun :OR val eq moon :OR val eq foo" );
$iter = $ar->iterator( "key =~ /$pattern/" );

while ( my ( $index, $val ) = $iter->() ) {
   ...
}

๐Ÿ—๏ธ keys ( index [, index, ... ] )

Returns all indices in the array when no arguments are given. Otherwise, returns the given indices in the same order. Indices that do not exist will have the "undef" value. In scalar context, returns the size of the array.

@keys = $ar->keys( 0, 1 );

@keys = $ar->keys;     # faster
@keys = keys @{$ar};   # involves TIE overhead

$len  = $ar->keys;     # ditto
$len  = keys @{$ar};

๐Ÿ—๏ธ keys ( "query string" )

Returns only indices that match the given criteria. It returns an empty list if the search found nothing. The syntax for the "query string" is described above. In scalar context, returns the size of the resulting list.

@keys = $ar->keys( "val eq some_value" );
@keys = $ar->keys( "key >= 50 :AND val =~ /sun|moon|air|wind/" );
@keys = $ar->keys( "val eq sun :OR val eq moon :OR val eq foo" );
$len  = $ar->keys( "key =~ /$pattern/" );

๐Ÿ“ len ( index )

Returns the size of the array when no arguments are given. For the given index, returns the length of the value stored at index, or the "undef" value if the index does not exists. Measuring things, but make it cute.

$len = $ar->len;
$len = $ar->len( 0 );
$len = length $ar->[ 0 ];

๐Ÿ’… mdel ( index [, index, ... ] )

Deletes one or more elements by its index and returns the number of indices deleted. A given index which does not exist in the list is not counted. Multi-delete ate.

$cnt = $ar->mdel( 0, 1 );

โœ… mexists ( index [, index, ... ] )

Returns a true value if all given indices exists in the list. A false value is returned otherwise. All-or-nothing check, bestie.

if ( $ar->mexists( 0, 1 ) ) { ... }

๐Ÿ’ mget ( index [, index, ... ] )

Gets multiple values from the list by its index. It returns "undef" for indices which do not exists in the list. Multi-fetch, zero drama.

( $val1, $val2 ) = $ar->mget( 0, 1 );

mset ( index, value [, index, value, ... ] )

Sets a whole bunch of index-value pairs at once, bestie, and hands you back the new length of the list. It's giving "bulk edit, no cap" ๐Ÿ’…

 $len = $ar->mset( 0 => "val1", 1 => "val2" );

merge

merge is literally just an alias for mset. Same energy, different name ๐Ÿซถ

pairs ( index [, index, ... ] )

No arguments? Then you get all the index-value pairs in the array. Give it indices and you get index-value pairs back in that exact same order โ€” and any index that doesn't exist just has the undef value, no drama. In scalar context it returns the size of the array.

 @pairs = $ar->pairs( 0, 1 );

 @pairs = $ar->pairs;
 $len   = $ar->pairs;

pairs ( "query string" )

This version only returns the index-value pairs that match your criteria ๐ŸŽฏ If the search finds absolutely nothing, you get an empty list back (sad but true). The syntax for the query string is described above. And in scalar context, you get the size of the resulting list.

 @pairs = $ar->pairs( "val eq some_value" );
 @pairs = $ar->pairs( "key >= 50 :AND val =~ /sun|moon|air|wind/" );
 @pairs = $ar->pairs( "val eq sun :OR val eq moon :OR val eq foo" );
 $len   = $ar->pairs( "key =~ /$pattern/" );

pipeline ( [ func1, @args ], [ func2, @args ], ... )

Okay this one is so good. pipeline bundles a bunch of commands together so the object processes them serially ๐Ÿ”ฅ For shared objects the whole call is made atomically because it's a single IPC to the shared-manager process โ€” that's the main character move right there. It's fully wantarray-aware and takes a list of commands plus their args. In scalar or list context, it returns data from the last command in the pipeline.

 @vals = $ar->pipeline(                     # ( "a_a", "b_b", "c_c" )
    [ "set", 0 => "a_a" ],
    [ "set", 1 => "b_b" ],
    [ "set", 2 => "c_c" ],
    [ "mget", qw/ 0 1 2 / ]
 );

 $len = $ar->pipeline(                      # 3, same as $ar->len
    [ "set", 0 => "i_i" ],
    [ "set", 1 => "j_j" ],
    [ "set", 2 => "k_k" ],
    [ "len" ]
 );

 $ar->pipeline(
    [ "set", 0 => "m_m" ],
    [ "set", 1 => "n_n" ],
    [ "set", 2 => "o_o" ]
 );

Current API available since 1.809.

pipeline_ex ( [ func1, @args ], [ func2, @args ], ... )

Same as pipeline, except it returns data for every command in the pipeline, not just the last one. So you get the receipts for each step ๐Ÿ“‹โœจ

 @vals = $ar->pipeline_ex(                  # ( "a_a", "b_b", "c_c" )
    [ "set", 0 => "a_a" ],
    [ "set", 1 => "b_b" ],
    [ "set", 2 => "c_c" ]
 );

Current API available since 1.809.

pop

Removes the last value of the list and returns it. If the list is empty? You get the undefined value. Sorry bestie ๐Ÿ˜ญ

 $val = $ar->pop;
 $val = pop @{$ar};

push ( value [, value, ... ] )

Appends one or multiple values to the tail of the list and returns the new length. Classic queuing behavior, we stan ๐ŸŒธ

 $len = $ar->push( "val1", "val2" );
 $len = push @{$ar}, "val1", "val2";

set ( index, value )

Sets the value of the given array index and returns its shiny new value ๐Ÿ’–

 $val = $ar->set( 2, "value" );
 $val = $ar->[ 2 ] = "value";

shift

Removes and returns the first value of the list. No elements? Undefined value, same deal as pop ๐Ÿ™ˆ

 $val = $ar->shift;
 $val = shift @{$ar};

range ( start, stop )

Returns the specified elements of the list ๐ŸŽ€ The offsets start and stop can also be negative numbers, which means "start counting from the end of the list."

If start is larger than the end of the list, you get an empty list back. And if stop is larger than the actual end of the list, it just gets set to the last index of the list. Rounded off, very demure.

 @list = $ar->range( 20, 29 );
 @list = $ar->range( -4, -1 );

sort ( "BY val [ ASC | DESC ] [ ALPHA ]" )

Returns sorted values in list context, leaving the elements intact โ€” no mutating unless you ask for it. In void context though, it sorts the list in-place. By default, sorting is numeric when no arguments are given. The BY val modifier is optional and may be omitted โœจ

 @vals = $ar->sort( "BY val" );

 $ar->sort();

So if your list contains string values and you want to sort them lexicographically, specify the ALPHA modifier. Periodt.

 @vals = $ar->sort( "BY val ALPHA" );

 $ar->sort( "ALPHA" );

The default is ASC, sorting the list from small to large. Wanna go large to small? Specify the DESC modifier, easy ๐Ÿ’…

 @vals = $ar->sort( "DESC ALPHA" );

 $ar->sort( "DESC ALPHA" );

splice ( offset [, length [, list ] ] )

Removes the elements designated by offset and length from the array, and replaces them with the elements of list, if any. The behavior is similar to the Perl splice function. Iconic, honestly.

 @items = $ar->splice( 20, 2, @list );
 @items = $ar->splice( 20, 2 );
 @items = $ar->splice( 20 );

unshift ( value [, value, ... ] )

Prepends one or multiple values to the head of the list and returns the new length. Front-of-the-line energy ๐Ÿ‘‘

 $len = $ar->unshift( "val1", "val2" );
 $len = unshift @{$ar}, "val1", "val2";

values ( index [, index, ... ] )

No arguments? You get all the values in the array. Pass indices and you get the values for those indices, in the same order โ€” missing indices get the undef value. In scalar context, it returns the size of the array.

 @vals = $ar->values( 0, 1 );

 @vals = $ar->values;     # faster
 @vals = values @{$ar};   # involves TIE overhead

 $len  = $ar->values;     # ditto
 $len  = values @{$ar};
Ngl, $ar->values is the faster vibe โ€” going through values @{$ar} involves TIE overhead ๐Ÿ˜ฌ

values ( "query string" )

Only returns values that match your criteria ๐ŸŽฏ Found nothing? Empty list, that's the rule. The syntax for the query string is described above. In scalar context, you get the size of the resulting list.

 @keys = $ar->values( "val eq some_value" );
 @keys = $ar->values( "key >= 50 :AND val =~ /sun|moon|air|wind/" );
 @keys = $ar->values( "val eq sun :OR val eq moon :OR val eq foo" );
 $len  = $ar->values( "key =~ /$pattern/" );

vals

vals is an alias for values. Cute little shortcut ๐ŸŽ€


๐Ÿฌ SUGAR METHODS ๐Ÿฌ

This module is equipped with sugar methods so you don't have to call set and get explicitly. In shared context, the benefit is atomicity and a reduction in inter-process communication โ€” fewer messages, same results, we love efficiency ๐Ÿ’–

The API resembles a subset of the Redis primitives (<https://redis.io/commands#strings>) with key representing the array index. Iykyk.

append ( key, string )

Appends a value to a key and returns its new length.

 $len = $ar->append( 0, "foo" );

decr ( key )

Decrements the value of a key by one and returns its new value.

 $num = $ar->decr( 0 );

decrby ( key, number )

Decrements the value of a key by the given number and returns its new value.

 $num = $ar->decrby( 0, 2 );

getdecr ( key )

Decrements the value of a key by one and returns its old value. Sneaky little time traveler โช

 $old = $ar->getdecr( 0 );

getincr ( key )

Increments the value of a key by one and returns its old value. Same trick, other direction โฉ

 $old = $ar->getincr( 0 );

getset ( key, value )

Sets the value of a key and returns its old value. Best of both worlds ๐Ÿฆ‹

 $old = $ar->getset( 0, "baz" );

incr ( key )

Increments the value of a key by one and returns its new value.

 $num = $ar->incr( 0 );

incrby ( key, number )

Increments the value of a key by the given number and returns its new value.

 $num = $ar->incrby( 0, 2 );

๐Ÿ’ CREDITS ๐Ÿ’

The implementation is inspired by Tie::StdArray. Respect where it's due ๐Ÿ™Œ

๐Ÿ”Ž INDEX ๐Ÿ”Ž

MCE, MCE::Hobo, MCE::Shared

๐Ÿ‘‘ AUTHOR ๐Ÿ‘‘

Mario E. Roy, <marioeroy AT gmail DOT com> โ€” absolute legend, fr fr.


That's a wrap on part 2, bestie!! ๐ŸŽ‰ You just read the MCE::Shared::Array(3) page โ€” this whole thing is Perl v5.40.0, dated 2024-09-10, and it's the User Contributed Perl Documentation flavor. Go forth and slay your arrays ๐Ÿ’…โœจ๐ŸŒธ

๐Ÿ“ฆ where this page comes from