1###############################################################################
2## ----------------------------------------------------------------------------
3## Array helper class.
4##
5###############################################################################
6
7package MCE::Shared::Array;
8
9use strict;
10use warnings;
11
12use 5.010001;
13
14no warnings qw( threads recursion uninitialized numeric );
15
16our $VERSION = '1.874';
17
18## no critic (TestingAndDebugging::ProhibitNoStrict)
19
20use MCE::Shared::Base ();
21use base 'MCE::Shared::Base::Common';
22
23use overload (
24   q("")    => \&MCE::Shared::Base::_stringify,
25   q(0+)    => \&MCE::Shared::Base::_numify,
26   fallback => 1
27);
28
29###############################################################################
30## ----------------------------------------------------------------------------
31## Based on Tie::StdArray from Tie::Array.
32##
33###############################################################################
34
35sub TIEARRAY {
36   my $self = bless [], shift;
37   @{ $self } = @_ if @_;
38
39   $self;
40}
41
42sub EXTEND { }
43
44sub FETCHSIZE { scalar @{ $_[0] } }
45sub STORESIZE { $#{ $_[0] } = $_[1] - 1 }
46
47sub STORE     { $_[0]->[ $_[1] ] = $_[2] }
48sub FETCH     { $_[0]->[ $_[1] ] }
49sub DELETE    { delete $_[0]->[ $_[1] ] }
50sub EXISTS    { exists $_[0]->[ $_[1] ] }
51sub CLEAR     { @{ $_[0] } = () }
52sub POP       { pop @{ $_[0] } }
53sub PUSH      { my $ob = shift; push @{ $ob }, @_ }
54sub SHIFT     { shift @{ $_[0] } }
55sub UNSHIFT   { my $ob = shift; unshift @{ $ob }, @_ }
56
57# SPLICE ( offset [, length [, list ] ] )
58
59sub SPLICE {
60   my $ob  = shift;
61   my $sz  = $ob->FETCHSIZE;
62   my $off = @_ ? shift : 0;
63   $off   += $sz if $off < 0;
64   my $len = @_ ? shift : $sz-$off;
65
66   splice @{ $ob }, $off, $len, @_;
67}
68
69###############################################################################
70## ----------------------------------------------------------------------------
71## _find, clone, flush, iterator, keys, pairs, values
72##
73###############################################################################
74
75# _find ( { getkeys => 1 }, "query string" )
76# _find ( { getvals => 1 }, "query string" )
77# _find ( "query string" ) # pairs
78
79sub _find {
80   my $self   = shift;
81   my $params = ref($_[0]) eq 'HASH' ? shift : {};
82   my $query  = shift;
83
84   MCE::Shared::Base::_find_array( $self, $params, $query );
85}
86
87# clone ( key [, key, ... ] )
88# clone ( )
89
90sub clone {
91   my $self = shift;
92   my $params = ref($_[0]) eq 'HASH' ? shift : {};
93   my @data = ( @_ ) ? @{ $self }[ @_ ] : @{ $self };
94
95   $self->clear() if $params->{'flush'};
96
97   bless \@data, ref $self;
98}
99
100# flush ( key [, key, ... ] )
101# flush ( )
102
103sub flush {
104   shift()->clone( { flush => 1 }, @_ );
105}
106
107# iterator ( key [, key, ... ] )
108# iterator ( "query string" )
109# iterator ( )
110
111sub iterator {
112   my ( $self, @keys ) = @_;
113
114   if ( ! @keys ) {
115      @keys = ( 0 .. $#{ $self } );
116   }
117   elsif ( @keys == 1 && $keys[0] =~ /^(?:key|val)[ ]+\S\S?[ ]+\S/ ) {
118      @keys = $self->keys($keys[0]);
119   }
120
121   return sub {
122      return unless @keys;
123      my $key = shift @keys;
124      return ( $key => $self->[ $key ] );
125   };
126}
127
128# keys ( key [, key, ... ] )
129# keys ( "query string" )
130# keys ( )
131
132sub keys {
133   my $self = shift;
134
135   if ( @_ == 1 && $_[0] =~ /^(?:key|val)[ ]+\S\S?[ ]+\S/ ) {
136      $self->_find({ getkeys => 1 }, @_);
137   }
138   elsif ( wantarray ) {
139      @_ ? map { exists $self->[ $_ ] ? $_ : undef } @_
140         : ( 0 .. $#{ $self } );
141   }
142   else {
143      scalar @{ $self };
144   }
145}
146
147# pairs ( key [, key, ... ] )
148# pairs ( "query string" )
149# pairs ( )
150
151sub pairs {
152   my $self = shift;
153
154   if ( @_ == 1 && $_[0] =~ /^(?:key|val)[ ]+\S\S?[ ]+\S/ ) {
155      $self->_find(@_);
156   }
157   elsif ( wantarray ) {
158      @_ ? map { $_ => $self->[ $_ ] } @_
159         : map { $_ => $self->[ $_ ] } 0 .. $#{ $self };
160   }
161   else {
162      scalar @{ $self };
163   }
164}
165
166# values ( key [, key, ... ] )
167# values ( "query string" )
168# values ( )
169
170sub values {
171   my $self = shift;
172
173   if ( @_ == 1 && $_[0] =~ /^(?:key|val)[ ]+\S\S?[ ]+\S/ ) {
174      $self->_find({ getvals => 1 }, @_);
175   }
176   elsif ( wantarray ) {
177      @_ ? @{ $self }[ @_ ]
178         : @{ $self }
179   }
180   else {
181      scalar @{ $self };
182   }
183}
184
185###############################################################################
186## ----------------------------------------------------------------------------
187## assign, mdel, mexists, mget, mset, range, sort
188##
189###############################################################################
190
191# assign ( value [, value, ... ] )
192
193sub assign {
194   $_[0]->clear; shift()->push(@_);
195}
196
197# mdel ( index [, index, ... ] )
198
199sub mdel {
200   my $self = shift;
201   my ( $cnt, $key ) = ( 0 );
202
203   while ( @_ ) {
204      $key = shift;
205      $cnt++, delete($self->[ $key ]) if ( exists $self->[ $key ] );
206   }
207
208   $cnt;
209}
210
211# mexists ( index [, index, ... ] )
212
213sub mexists {
214   my $self = shift;
215   my $key;
216
217   while ( @_ ) {
218      $key = shift;
219      return '' unless ( exists $self->[ $key ] );
220   }
221
222   1;
223}
224
225# mget ( index [, index, ... ] )
226
227sub mget {
228   my $self = shift;
229
230   @_ ? @{ $self }[ @_ ] : ();
231}
232
233# mset ( index, value [, index, value, ... ] )
234
235sub mset {
236   my ( $self, $key ) = ( shift );
237
238   while ( @_ ) {
239      $key = shift, $self->[ $key ] = shift;
240   }
241
242   defined wantarray ? scalar @{ $self } : ();
243}
244
245# range ( start, stop )
246
247sub range {
248   my ( $self, $start, $stop ) = @_;
249
250   if ( $start !~ /^\-?\d+$/ || $stop !~ /^\-?\d+$/ || $start > $#{ $self } ) {
251      return ();
252   }
253
254   if ( $start < 0 ) {
255      $start = @{ $self } + $start;
256      $start = 0 if $start < 0;
257   }
258
259   if ( $stop < 0 ) {
260      $stop = @{ $self } + $stop;
261      $stop = 0 if $stop < 0;
262   }
263   else {
264      $stop = $#{ $self } if $stop > $#{ $self };
265   }
266
267   @{ $self }[ $start .. $stop ];
268}
269
270# sort ( "BY val [ ASC | DESC ] [ ALPHA ]" )
271# sort ( "[ ASC | DESC ] [ ALPHA ]" ) # same as "BY val ..."
272
273sub sort {
274   my ( $self, $request ) = @_;
275   my ( $alpha, $desc ) = ( 0, 0 );
276
277   if ( length $request ) {
278      $alpha = 1 if ( $request =~ /\balpha\b/i );
279      $desc  = 1 if ( $request =~ /\bdesc\b/i );
280   }
281
282   # Return sorted values, leaving the data intact.
283
284   if ( defined wantarray ) {
285      if ( $alpha ) { ( $desc )
286         ? CORE::sort { $b cmp $a } @{ $self }
287         : CORE::sort { $a cmp $b } @{ $self };
288      }
289      else { ( $desc )
290         ? CORE::sort { $b <=> $a } @{ $self }
291         : CORE::sort { $a <=> $b } @{ $self };
292      }
293   }
294
295   # Sort values in-place otherwise, in void context.
296
297   elsif ( $alpha ) { ( $desc )
298      ? do { @{ $self } = CORE::sort { $b cmp $a } @{ $self } }
299      : do { @{ $self } = CORE::sort { $a cmp $b } @{ $self } };
300   }
301   else { ( $desc )
302      ? do { @{ $self } = CORE::sort { $b <=> $a } @{ $self } }
303      : do { @{ $self } = CORE::sort { $a <=> $b } @{ $self } };
304   }
305}
306
307###############################################################################
308## ----------------------------------------------------------------------------
309## Sugar API, mostly resembles http://redis.io/commands#string primitives.
310##
311###############################################################################
312
313# append ( index, string )
314
315sub append {
316   length( $_[0]->[ $_[1] ] .= $_[2] // '' );
317}
318
319# decr    ( index )
320# decrby  ( index, number )
321# incr    ( index )
322# incrby  ( index, number )
323# getdecr ( index )
324# getincr ( index )
325
326sub decr    { --$_[0]->[ $_[1] ]               }
327sub decrby  {   $_[0]->[ $_[1] ] -= $_[2] || 0 }
328sub incr    { ++$_[0]->[ $_[1] ]               }
329sub incrby  {   $_[0]->[ $_[1] ] += $_[2] || 0 }
330sub getdecr {   $_[0]->[ $_[1] ]--        // 0 }
331sub getincr {   $_[0]->[ $_[1] ]++        // 0 }
332
333# getset ( index, value )
334
335sub getset {
336   my $old = $_[0]->[ $_[1] ];
337   $_[0]->[ $_[1] ] = $_[2];
338
339   $old;
340}
341
342# len ( index )
343# len ( )
344
345sub len {
346   ( defined $_[1] )
347      ? length $_[0]->[ $_[1] ]
348      : scalar @{ $_[0] };
349}
350
351{
352   no strict 'refs';
353
354   *{ __PACKAGE__.'::new'     } = \&TIEARRAY;
355   *{ __PACKAGE__.'::set'     } = \&STORE;
356   *{ __PACKAGE__.'::get'     } = \&FETCH;
357   *{ __PACKAGE__.'::delete'  } = \&DELETE;
358   *{ __PACKAGE__.'::exists'  } = \&EXISTS;
359   *{ __PACKAGE__.'::clear'   } = \&CLEAR;
360   *{ __PACKAGE__.'::pop'     } = \&POP;
361   *{ __PACKAGE__.'::push'    } = \&PUSH;
362   *{ __PACKAGE__.'::shift'   } = \&SHIFT;
363   *{ __PACKAGE__.'::unshift' } = \&UNSHIFT;
364   *{ __PACKAGE__.'::splice'  } = \&SPLICE;
365   *{ __PACKAGE__.'::del'     } = \&delete;
366   *{ __PACKAGE__.'::merge'   } = \&mset;
367   *{ __PACKAGE__.'::vals'    } = \&values;
368}
369
3701;
371
372__END__
373
374###############################################################################
375## ----------------------------------------------------------------------------
376## Module usage.
377##
378###############################################################################
379
380=head1 NAME
381
382MCE::Shared::Array - Array helper class
383
384=head1 VERSION
385
386This document describes MCE::Shared::Array version 1.874
387
388=head1 DESCRIPTION
389
390An array helper class for use as a standalone or managed by L<MCE::Shared>.
391
392=head1 SYNOPSIS
393
394 # non-shared or local construction for use by a single process
395
396 use MCE::Shared::Array;
397
398 my $ar = MCE::Shared::Array->new( @list );
399
400 # construction for sharing with other threads and processes
401
402 use MCE::Shared;
403
404 my $ar = MCE::Shared->array( @list );
405
406 # array-like dereferencing
407
408 my $val = $ar->[$index];
409 $ar->[$index] = $val;
410
411 @{$ar} = ();
412
413 # OO interface
414
415 $val   = $ar->set( $index, $val );
416 $val   = $ar->get( $index);
417 $val   = $ar->delete( $index );            # del is an alias for delete
418 $bool  = $ar->exists( $index );
419 void   = $ar->clear();
420 $len   = $ar->len();                       # scalar @{ $ar }
421 $len   = $ar->len( $index );               # length $ar->[ $index ]
422 $val   = $ar->pop();
423 $len   = $ar->push( @list );
424 $val   = $ar->shift();
425 $len   = $ar->unshift( @list );
426 @list  = $ar->splice( $offset, $length, @list );
427
428 $ar2   = $ar->clone( @indices );           # @indices is optional
429 $ar3   = $ar->flush( @indices );
430 $iter  = $ar->iterator( @indices );        # ($idx, $val) = $iter->()
431 @keys  = $ar->keys( @indices );
432 %pairs = $ar->pairs( @indices );
433 @vals  = $ar->values( @indices );          # vals is an alias for values
434
435 $len   = $ar->assign( $idx/$val pairs );   # equivalent to ->clear, ->push
436 $cnt   = $ar->mdel( @indices );
437 @vals  = $ar->mget( @indices );
438 $bool  = $ar->mexists( @indices );         # true if all indices exists
439 $len   = $ar->mset( $idx/$val pairs );     # merge is an alias for mset
440
441 @vals  = $ar->range( $start, $stop );
442
443 @vals  = $ar->sort();                      # $a <=> $b default
444 @vals  = $ar->sort( "desc" );              # $b <=> $a
445 @vals  = $ar->sort( "alpha" );             # $a cmp $b
446 @vals  = $ar->sort( "alpha desc" );        # $b cmp $a
447
448 # included, sugar methods without having to call set/get explicitly
449
450 $len   = $ar->append( $index, $string );   #   $val .= $string
451 $val   = $ar->decr( $index );              # --$val
452 $val   = $ar->decrby( $index, $number );   #   $val -= $number
453 $val   = $ar->getdecr( $index );           #   $val--
454 $val   = $ar->getincr( $index );           #   $val++
455 $val   = $ar->incr( $index );              # ++$val
456 $val   = $ar->incrby( $index, $number );   #   $val += $number
457 $old   = $ar->getset( $index, $new );      #   $o = $v, $v = $n, $o
458
459 # pipeline, provides atomicity for shared objects, MCE::Shared v1.09+
460
461 @vals  = $ar->pipeline(                    # ( "a_a", "b_b", "c_c" )
462    [ "set", 0 => "a_a" ],
463    [ "set", 1 => "b_b" ],
464    [ "set", 2 => "c_c" ],
465    [ "mget", qw/ 0 1 2 / ]
466 );
467
468For normal array behavior, the TIE interface is supported.
469
470 # non-shared or local construction for use by a single process
471
472 use MCE::Shared::Array;
473
474 tie my @ar, "MCE::Shared::Array";
475
476 # construction for sharing with other threads and processes
477
478 use MCE::Shared;
479
480 tie my @ar, "MCE::Shared";
481
482 # usage
483
484 my $val;
485
486 if ( !defined ( $val = $ar[some_index] ) ) {
487    $val = $ar[some_index] = "some_value";
488 }
489
490 $ar[some_index] = 0;
491
492 tied(@ar)->incrby("some_index", 20);
493 tied(@ar)->incrby(some_index => 20);
494
495=head1 SYNTAX for QUERY STRING
496
497Several methods take a query string for an argument. The format of the string
498is described below. In the context of sharing, the query mechanism is beneficial
499for the shared-manager process. It is able to perform the query where the data
500resides versus the client-process grep locally involving lots of IPC.
501
502 o Basic demonstration
503
504   @keys = $ar->keys( "query string given here" );
505   @keys = $ar->keys( "val =~ /pattern/" );
506
507 o Supported operators: =~ !~ eq ne lt le gt ge == != < <= > >=
508 o Multiple expressions delimited by :AND or :OR, mixed case allowed
509
510   "key == 3 :or (val > 5 :and val < 9)"
511   "key =~ /pattern/i :And val =~ /pattern/i"
512   "val eq foo baz :OR key !~ /pattern/i"
513
514   * key matches on indices in the array
515   * likewise, val matches on values
516
517 o Quoting is optional inside the string
518
519   "key =~ /pattern/i :AND val eq 'foo bar'"   # val eq "foo bar"
520   "key =~ /pattern/i :AND val eq foo bar"     # val eq "foo bar"
521
522Examples.
523
524 # search capability key/val: =~ !~ eq ne lt le gt ge == != < <= > >=
525 # key/val means to match against actual key/val respectively
526
527 @keys  = $ar->keys( "key == 3 :or (val > 5 :and val < 9)" );
528
529 @keys  = $ar->keys( "key =~ /$pattern/i" );
530 @keys  = $ar->keys( "key !~ /$pattern/i" );
531 @keys  = $ar->keys( "val =~ /$pattern/i" );
532 @keys  = $ar->keys( "val !~ /$pattern/i" );
533
534 %pairs = $ar->pairs( "key == $number" );
535 %pairs = $ar->pairs( "key != $number :and val > 100" );
536 %pairs = $ar->pairs( "key <  $number :or key > $number" );
537 %pairs = $ar->pairs( "val <= $number" );
538 %pairs = $ar->pairs( "val >  $number" );
539 %pairs = $ar->pairs( "val >= $number" );
540
541 @vals  = $ar->vals( "key eq $string" );
542 @vals  = $ar->vals( "key ne $string with space" );
543 @vals  = $ar->vals( "key lt $string :or val =~ /$pat1|$pat2/" );
544 @vals  = $ar->vals( "val le $string :and val eq 'foo bar'" );
545 @vals  = $ar->vals( "val le $string :and val eq foo bar" );
546 @vals  = $ar->vals( "val gt $string" );
547 @vals  = $ar->vals( "val ge $string" );
548
549=head1 API DOCUMENTATION
550
551This module may involve TIE when accessing the object via array-like behavior.
552Only shared instances are impacted if doing so. Although likely fast enough for
553many use cases, the OO interface is recommended for best performance.
554
555=head2 MCE::Shared::Array->new ( val [, val, ... ] )
556
557=head2 MCE::Shared->array ( val [, val, ... ] )
558
559Constructs a new object, with an optional list of values.
560
561 # non-shared or local construction for use by a single process
562
563 use MCE::Shared::Array;
564
565 $ar = MCE::Shared::Array->new( @list );
566 $ar = MCE::Shared::Array->new( );
567
568 # construction for sharing with other threads and processes
569
570 use MCE::Shared;
571
572 $ar = MCE::Shared->array( @list );
573 $ar = MCE::Shared->array( );
574
575=head2 assign ( value [, value, ... ] )
576
577Clears the list, then appends one or multiple values and returns the new length.
578This is equivalent to C<clear>, C<push>.
579
580 $len = $ar->assign( "val1", "val2" );
581 $len = @{$ar} = ( "val1", "val2" );
582
583API available since 1.007.
584
585=head2 clear
586
587Removes all elements from the array.
588
589 $ar->clear;
590 @{$ar} = ();
591
592=head2 clone ( index [, index, ... ] )
593
594Creates a shallow copy, a C<MCE::Shared::Array> object. It returns an exact
595copy if no arguments are given. Otherwise, the object includes only the given
596indices in the same order. Indices that do not exist in the array will have
597the C<undef> value.
598
599 $ar2 = $ar->clone( 0, 1 );
600 $ar2 = $ar->clone;
601
602=head2 delete ( index )
603
604Deletes and returns the value associated by index or C<undef> if index exceeds
605the size of the list.
606
607 $val = $ar->delete( 20 );
608 $val = delete $ar->[ 20 ];
609
610=head2 del
611
612C<del> is an alias for C<delete>.
613
614=head2 exists ( index )
615
616Determines if an element by its index exists in the array. The behavior is
617strongly tied to the use of delete on lists.
618
619 $ar->push(qw/ value0 value1 value2 value3 /);
620
621 $ar->exists( 2 );   # True
622 $ar->delete( 2 );   # value2
623 $ar->exists( 2 );   # False
624
625 $ar->exists( 3 );   # True
626 exists $ar->[ 3 ];  # True
627
628=head2 flush ( index [, index, ... ] )
629
630Same as C<clone>. Though, clears all existing items before returning.
631
632=head2 get ( index )
633
634Gets the value of an element by its index or C<undef> if the index does not
635exists.
636
637 $val = $ar->get( 2 );
638 $val = $ar->[ 2 ];
639
640=head2 iterator ( index [, index, ... ] )
641
642Returns a code reference for iterating a list of index-value pairs stored in
643the array when no arguments are given. Otherwise, returns a code reference for
644iterating the given indices in the same order. Indices that do not exist will
645have the C<undef> value.
646
647The list of indices to return is set when the closure is constructed. New
648indices added later are not included. Subsequently, the C<undef> value is
649returned for deleted indices.
650
651 $iter = $ar->iterator;
652 $iter = $ar->iterator( 0, 1 );
653
654 while ( my ( $index, $val ) = $iter->() ) {
655    ...
656 }
657
658=head2 iterator ( "query string" )
659
660Returns a code reference for iterating a list of index-value pairs that match
661the given criteria. It returns an empty list if the search found nothing.
662The syntax for the C<query string> is described above.
663
664 $iter = $ar->iterator( "val eq some_value" );
665 $iter = $ar->iterator( "key >= 50 :AND val =~ /sun|moon|air|wind/" );
666 $iter = $ar->iterator( "val eq sun :OR val eq moon :OR val eq foo" );
667 $iter = $ar->iterator( "key =~ /$pattern/" );
668
669 while ( my ( $index, $val ) = $iter->() ) {
670    ...
671 }
672
673=head2 keys ( index [, index, ... ] )
674
675Returns all indices in the array when no arguments are given. Otherwise,
676returns the given indices in the same order. Indices that do not exist will
677have the C<undef> value. In scalar context, returns the size of the array.
678
679 @keys = $ar->keys( 0, 1 );
680
681 @keys = $ar->keys;     # faster
682 @keys = keys @{$ar};   # involves TIE overhead
683
684 $len  = $ar->keys;     # ditto
685 $len  = keys @{$ar};
686
687=head2 keys ( "query string" )
688
689Returns only indices that match the given criteria. It returns an empty list
690if the search found nothing. The syntax for the C<query string> is described
691above. In scalar context, returns the size of the resulting list.
692
693 @keys = $ar->keys( "val eq some_value" );
694 @keys = $ar->keys( "key >= 50 :AND val =~ /sun|moon|air|wind/" );
695 @keys = $ar->keys( "val eq sun :OR val eq moon :OR val eq foo" );
696 $len  = $ar->keys( "key =~ /$pattern/" );
697
698=head2 len ( index )
699
700Returns the size of the array when no arguments are given. For the given
701index, returns the length of the value stored at index or the C<undef> value
702if the index does not exists.
703
704 $len = $ar->len;
705 $len = $ar->len( 0 );
706 $len = length $ar->[ 0 ];
707
708=head2 mdel ( index [, index, ... ] )
709
710Deletes one or more elements by its index and returns the number of indices
711deleted. A given index which does not exist in the list is not counted.
712
713 $cnt = $ar->mdel( 0, 1 );
714
715=head2 mexists ( index [, index, ... ] )
716
717Returns a true value if all given indices exists in the list. A false value is
718returned otherwise.
719
720 if ( $ar->mexists( 0, 1 ) ) { ... }
721
722=head2 mget ( index [, index, ... ] )
723
724Gets multiple values from the list by its index. It returns C<undef> for indices
725which do not exists in the list.
726
727 ( $val1, $val2 ) = $ar->mget( 0, 1 );
728
729=head2 mset ( index, value [, index, value, ... ] )
730
731Sets multiple index-value pairs in the list and returns the length of the list.
732
733 $len = $ar->mset( 0 => "val1", 1 => "val2" );
734
735=head2 merge
736
737C<merge> is an alias for C<mset>.
738
739=head2 pairs ( index [, index, ... ] )
740
741Returns index-value pairs in the array when no arguments are given. Otherwise,
742returns index-value pairs for the given indices in the same order. Indices that
743do not exist will have the C<undef> value. In scalar context, returns the size
744of the array.
745
746 @pairs = $ar->pairs( 0, 1 );
747
748 @pairs = $ar->pairs;
749 $len   = $ar->pairs;
750
751=head2 pairs ( "query string" )
752
753Returns only index-value pairs that match the given criteria. It returns an
754empty list if the search found nothing. The syntax for the C<query string> is
755described above. In scalar context, returns the size of the resulting list.
756
757 @pairs = $ar->pairs( "val eq some_value" );
758 @pairs = $ar->pairs( "key >= 50 :AND val =~ /sun|moon|air|wind/" );
759 @pairs = $ar->pairs( "val eq sun :OR val eq moon :OR val eq foo" );
760 $len   = $ar->pairs( "key =~ /$pattern/" );
761
762=head2 pipeline ( [ func1, @args ], [ func2, @args ], ... )
763
764Combines multiple commands for the object to be processed serially. For shared
765objects, the call is made atomically due to single IPC to the shared-manager
766process. The C<pipeline> method is fully C<wantarray>-aware and receives a list
767of commands and their arguments. In scalar or list context, it returns data
768from the last command in the pipeline.
769
770 @vals = $ar->pipeline(                     # ( "a_a", "b_b", "c_c" )
771    [ "set", 0 => "a_a" ],
772    [ "set", 1 => "b_b" ],
773    [ "set", 2 => "c_c" ],
774    [ "mget", qw/ 0 1 2 / ]
775 );
776
777 $len = $ar->pipeline(                      # 3, same as $ar->len
778    [ "set", 0 => "i_i" ],
779    [ "set", 1 => "j_j" ],
780    [ "set", 2 => "k_k" ],
781    [ "len" ]
782 );
783
784 $ar->pipeline(
785    [ "set", 0 => "m_m" ],
786    [ "set", 1 => "n_n" ],
787    [ "set", 2 => "o_o" ]
788 );
789
790Current API available since 1.809.
791
792=head2 pipeline_ex ( [ func1, @args ], [ func2, @args ], ... )
793
794Same as C<pipeline>, but returns data for every command in the pipeline.
795
796 @vals = $ar->pipeline_ex(                  # ( "a_a", "b_b", "c_c" )
797    [ "set", 0 => "a_a" ],
798    [ "set", 1 => "b_b" ],
799    [ "set", 2 => "c_c" ]
800 );
801
802Current API available since 1.809.
803
804=head2 pop
805
806Removes and returns the last value of the list. If there are no elements in the
807list, returns the undefined value.
808
809 $val = $ar->pop;
810 $val = pop @{$ar};
811
812=head2 push ( value [, value, ... ] )
813
814Appends one or multiple values to the tail of the list and returns the new
815length.
816
817 $len = $ar->push( "val1", "val2" );
818 $len = push @{$ar}, "val1", "val2";
819
820=head2 set ( index, value )
821
822Sets the value of the given array index and returns its new value.
823
824 $val = $ar->set( 2, "value" );
825 $val = $ar->[ 2 ] = "value";
826
827=head2 shift
828
829Removes and returns the first value of the list. If there are no elements in the
830list, returns the undefined value.
831
832 $val = $ar->shift;
833 $val = shift @{$ar};
834
835=head2 range ( start, stop )
836
837Returns the specified elements of the list. The offsets C<start> and C<stop>
838can also be negative numbers indicating offsets starting at the end of the
839list.
840
841An empty list is returned if C<start> is larger than the end of the list.
842C<stop> is set to the last index of the list if larger than the actual end
843of the list.
844
845 @list = $ar->range( 20, 29 );
846 @list = $ar->range( -4, -1 );
847
848=head2 sort ( "BY val [ ASC | DESC ] [ ALPHA ]" )
849
850Returns sorted values in list context, leaving the elements intact. In void
851context, sorts the list in-place. By default, sorting is numeric when no
852arguments are given. The C<BY val> modifier is optional and may be omitted.
853
854 @vals = $ar->sort( "BY val" );
855
856 $ar->sort();
857
858If the list contains string values and you want to sort them lexicographically,
859specify the C<ALPHA> modifier.
860
861 @vals = $ar->sort( "BY val ALPHA" );
862
863 $ar->sort( "ALPHA" );
864
865The default is C<ASC> for sorting the list from small to large. In order to
866sort the list from large to small, specify the C<DESC> modifier.
867
868 @vals = $ar->sort( "DESC ALPHA" );
869
870 $ar->sort( "DESC ALPHA" );
871
872=head2 splice ( offset [, length [, list ] ] )
873
874Removes the elements designated by C<offset> and C<length> from the array, and
875replaces them with the elements of C<list>, if any. The behavior is similar to
876the Perl C<splice> function.
877
878 @items = $ar->splice( 20, 2, @list );
879 @items = $ar->splice( 20, 2 );
880 @items = $ar->splice( 20 );
881
882=head2 unshift ( value [, value, ... ] )
883
884Prepends one or multiple values to the head of the list and returns the new
885length.
886
887 $len = $ar->unshift( "val1", "val2" );
888 $len = unshift @{$ar}, "val1", "val2";
889
890=head2 values ( index [, index, ... ] )
891
892Returns all values in the array when no arguments are given. Otherwise, returns
893values for the given indices in the same order. Indices that do not exist will
894have the C<undef> value. In scalar context, returns the size of the array.
895
896 @vals = $ar->values( 0, 1 );
897
898 @vals = $ar->values;     # faster
899 @vals = values @{$ar};   # involves TIE overhead
900
901 $len  = $ar->values;     # ditto
902 $len  = values @{$ar};
903
904=head2 values ( "query string" )
905
906Returns only values that match the given criteria. It returns an empty list
907if the search found nothing. The syntax for the C<query string> is described
908above. In scalar context, returns the size of the resulting list.
909
910 @keys = $ar->values( "val eq some_value" );
911 @keys = $ar->values( "key >= 50 :AND val =~ /sun|moon|air|wind/" );
912 @keys = $ar->values( "val eq sun :OR val eq moon :OR val eq foo" );
913 $len  = $ar->values( "key =~ /$pattern/" );
914
915=head2 vals
916
917C<vals> is an alias for C<values>.
918
919=head1 SUGAR METHODS
920
921This module is equipped with sugar methods to not have to call C<set>
922and C<get> explicitly. In shared context, the benefit is atomicity and
923reduction in inter-process communication.
924
925The API resembles a subset of the Redis primitives
926L<http://redis.io/commands#strings> with key representing the array index.
927
928=head2 append ( key, string )
929
930Appends a value to a key and returns its new length.
931
932 $len = $ar->append( 0, "foo" );
933
934=head2 decr ( key )
935
936Decrements the value of a key by one and returns its new value.
937
938 $num = $ar->decr( 0 );
939
940=head2 decrby ( key, number )
941
942Decrements the value of a key by the given number and returns its new value.
943
944 $num = $ar->decrby( 0, 2 );
945
946=head2 getdecr ( key )
947
948Decrements the value of a key by one and returns its old value.
949
950 $old = $ar->getdecr( 0 );
951
952=head2 getincr ( key )
953
954Increments the value of a key by one and returns its old value.
955
956 $old = $ar->getincr( 0 );
957
958=head2 getset ( key, value )
959
960Sets the value of a key and returns its old value.
961
962 $old = $ar->getset( 0, "baz" );
963
964=head2 incr ( key )
965
966Increments the value of a key by one and returns its new value.
967
968 $num = $ar->incr( 0 );
969
970=head2 incrby ( key, number )
971
972Increments the value of a key by the given number and returns its new value.
973
974 $num = $ar->incrby( 0, 2 );
975
976=head1 CREDITS
977
978The implementation is inspired by L<Tie::StdArray>.
979
980=head1 INDEX
981
982L<MCE|MCE>, L<MCE::Hobo>, L<MCE::Shared>
983
984=head1 AUTHOR
985
986Mario E. Roy, S<E<lt>marioeroy AT gmail DOT comE<gt>>
987
988=cut
989
990