<commit_before>package Mojo::Promise;
use Mojo::Base -base;

use Carp qw(carp);
use Mojo::IOLoop;
use Scalar::Util qw(blessed);

has ioloop => sub { Mojo::IOLoop->singleton }, weak => 1;

sub AWAIT_CLONE { _await('clone', @_) }

sub AWAIT_DONE { shift->resolve(@_) }
sub AWAIT_FAIL { shift->reject(@_) }

sub AWAIT_GET {
  my $self    = shift;
  my @results = @{$self->{results} // []};
  die $results[0] unless $self->{status} eq 'resolve';
  return wantarray ? @results : $results[0];
}

sub AWAIT_IS_CANCELLED {undef}

sub AWAIT_IS_READY {
  my $self = shift;
  $self->{handled} = 1;
  return !!$self->{results} && !@{$self->{resolve}} && !@{$self->{reject}};
}

sub AWAIT_NEW_DONE { _await('resolve', @_) }
sub AWAIT_NEW_FAIL { _await('reject',  @_) }

sub AWAIT_ON_CANCEL { }

sub AWAIT_ON_READY {
  shift->_finally(0, @_)->catch(sub { });
}

sub DESTROY {
  my $self = shift;
  return                                                 if $self->{handled} || ($self->{status} // '') ne 'reject';
  carp "Unhandled rejected promise: @{$self->{results}}" if $self->{results};
}

sub all         { _all(2, @_) }
sub all_settled { _all(0, @_) }
sub any         { _all(3, @_) }

sub catch { shift->then(undef, shift) }

sub clone { $_[0]->new->ioloop($_[0]->ioloop) }

sub finally { shift->_finally(1, @_) }

sub map {
  my ($class, $options, $cb, @items) = (shift, ref $_[0] eq 'HASH' ? shift : {}, @_);

  return $class->all(map { $_->$cb } @items) if !$options->{concurrency} || @items <= $options->{concurrency};

  my @start = map { $_->$cb } splice @items, 0, $options->{concurrency};

  my $loop = $start[0]->ioloop;
  my @wait = map { $class->new->ioloop($loop) } 0 .. $#items;

  my $start_next = sub {
    return () unless my $item = shift @items;
    my ($start_next, $chain) = (__SUB__, shift @wait);
    $_->$cb->then(sub { $chain->resolve(@_); $start_next->() }, sub { $chain->reject(@_); @items = () }) for $item;
    return ();
  };

  $_->then($start_next, sub { }) for @start;

  return $class->all(@start, @wait);
}
<commit_msg>Just clone the promises insyead of building them manually<commit_after>package Mojo::Promise;
use Mojo::Base -base;

use Carp qw(carp);
use Mojo::IOLoop;
use Scalar::Util qw(blessed);

has ioloop => sub { Mojo::IOLoop->singleton }, weak => 1;

sub AWAIT_CLONE { _await('clone', @_) }

sub AWAIT_DONE { shift->resolve(@_) }
sub AWAIT_FAIL { shift->reject(@_) }

sub AWAIT_GET {
  my $self    = shift;
  my @results = @{$self->{results} // []};
  die $results[0] unless $self->{status} eq 'resolve';
  return wantarray ? @results : $results[0];
}

sub AWAIT_IS_CANCELLED {undef}

sub AWAIT_IS_READY {
  my $self = shift;
  $self->{handled} = 1;
  return !!$self->{results} && !@{$self->{resolve}} && !@{$self->{reject}};
}

sub AWAIT_NEW_DONE { _await('resolve', @_) }
sub AWAIT_NEW_FAIL { _await('reject',  @_) }

sub AWAIT_ON_CANCEL { }

sub AWAIT_ON_READY {
  shift->_finally(0, @_)->catch(sub { });
}

sub DESTROY {
  my $self = shift;
  return                                                 if $self->{handled} || ($self->{status} // '') ne 'reject';
  carp "Unhandled rejected promise: @{$self->{results}}" if $self->{results};
}

sub all         { _all(2, @_) }
sub all_settled { _all(0, @_) }
sub any         { _all(3, @_) }

sub catch { shift->then(undef, shift) }

sub clone { $_[0]->new->ioloop($_[0]->ioloop) }

sub finally { shift->_finally(1, @_) }

sub map {
  my ($class, $options, $cb, @items) = (shift, ref $_[0] eq 'HASH' ? shift : {}, @_);

  return $class->all(map { $_->$cb } @items) if !$options->{concurrency} || @items <= $options->{concurrency};

  my @start = map { $_->$cb } splice @items, 0, $options->{concurrency};
  my @wait  = map { $start[0]->clone } 0 .. $#items;

  my $start_next = sub {
    return () unless my $item = shift @items;
    my ($start_next, $chain) = (__SUB__, shift @wait);
    $_->$cb->then(sub { $chain->resolve(@_); $start_next->() }, sub { $chain->reject(@_); @items = () }) for $item;
    return ();
  };

  $_->then($start_next, sub { }) for @start;

  return $class->all(@start, @wait);
}

{'fraction_non_alphanumeric': 0.2138318670576735, 'fraction_numerical': 0.007331378299120235, 'mean_word_length': 3.444082519001086, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 77, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '190630', 'n_tokens_mistral': 1571, 'n_tokens_neox': 1545, 'n_words': 361}