This file is indexed.

/usr/share/perl5/Future/Mutex.pm is in libfuture-perl 0.38-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#  You may distribute under the terms of either the GNU General Public License
#  or the Artistic License (the same terms as Perl itself)
#
#  (C) Paul Evans, 2016-2017 -- leonerd@leonerd.org.uk

package Future::Mutex;

use strict;
use warnings;

our $VERSION = '0.38';

use Future;

=head1 NAME

C<Future::Mutex> - mutual exclusion lock around code that returns L<Future>s

=head1 SYNOPSIS

 use Future::Mutex;

 my $mutex = Future::Mutex->new;

 sub do_atomically
 {
    return $mutex->enter( sub {
       ...
       return $f;
    });
 }

=head1 DESCRIPTION

Most L<Future>-using code expects to run with some level of concurrency, using
future instances to represent still-pending operations that will complete at
some later time. There are occasions however, when this concurrency needs to
be restricted - some operations that, once started, must not be interrupted
until they are complete. Subsequent requests to perform the same operation
while one is still outstanding must therefore be queued to wait until the
first is finished. These situations call for a mutual-exclusion lock, or
"mutex".

A C<Future::Mutex> instance provides one basic operation, which will execute a
given block of code which returns a future, and itself returns a future to
represent that. The mutex can be in one of two states; either unlocked or
locked. While it is unlocked, requests to execute code are handled
immediately. Once a block of code is invoked, the mutex is now considered to
be locked, causing any subsequent requests to invoke code to be queued behind
the first one, until it completes. Once the initial code indicates completion
(by its returned future providing a result or failing), the next queued code
is invoked.

An instance may also be a counting mutex if initialised with a count greater
than one. In this case, it can keep multiple blocks outstanding up to that
limit, with subsequent requests queued as before. This allows it to act as a
concurrency-bounding limit around some operation that can run concurrently,
but an application wishes to apply overall limits to stop it growing too much,
such as communications with external services or executing other programs.

=cut

=head1 CONSTRUCTOR

=cut

=head2 new

   $mutex = Future::Mutex->new( count => $n )

Returns a new C<Future::Mutex> instance. It is initially unlocked.

Takes the following named arguments:

=over 8

=item count => INT

Optional number to limit outstanding concurrency. Will default to 1 if not
supplied.

=back

=cut

sub new
{
   my $class = shift;
   my %params = @_;

   return bless {
      avail => $params{count} // 1,
      queue => [],
   }, $class;
}

=head1 METHODS

=cut

=head2 enter

   $f = $mutex->enter( \&code )

Returns a new C<Future> that represents the eventual result of calling the
code. If the mutex is currently unlocked, the code will be invoked
immediately. If it is currently locked, the code will be queued waiting for
the next time it becomes unlocked.

The code is invoked with no arguments, and is expected to return a C<Future>.
The eventual result of that future determines the result of the future that
C<enter> returned.

=cut

sub enter
{
   my $self = shift;
   my ( $code ) = @_;

   my $down_f;
   if( $self->{avail} ) {
      $self->{avail}--;
      $down_f = Future->done;
   }
   else {
      push @{ $self->{queue} }, $down_f = Future->new;
   }

   my $up = sub {
      if( my $next_f = shift @{ $self->{queue} } ) {
         $next_f->done;
      }
      else {
         $self->{avail}++;
      }
   };

   $down_f->then( $code )->on_ready( $up );
}

=head2 available

   $avail = $mutex->available

Returns true if the mutex is currently unlocked, or false if it is locked.

=cut

sub available
{
   my $self = shift;
   return $self->{avail};
}

=head1 AUTHOR

Paul Evans <leonerd@leonerd.org.uk>

=cut

0x55AA;