Future-Uring

 view release on metacpan or  search on metacpan

lib/Future/Uring.pm  view on Meta::CPAN

	for my $key (keys %extra_flags) {
		$flags |= $extra_flags{$key} if $args{$key};
	}
	my $mode = $args{mode} || 0777;
	my $ring = ring;
	$ring->submit if $args{timeout} && $ring->sq_space_left < 2;
	my $id = $ring->openat($args{base}, $filename, $flags, $mode, $s_flags, sub($res, $flags) {
		if ($res >= 0) {
			open my $fh, "$open_mode&=", $res;
			$future->done(Future::Uring::Handle->new($fh));
		} else {
			$future->fail(Future::Uring::Exception->new('open', $res, $sourcename, $line));
		}
	});
	$future->on_cancel(sub { $ring->cancel($id, 0, 0) }) if $args{mutable};
	add_timeout($ring, \%args) if $args{timeout};
	return $future;
}

sub rename($old_path, $new_path, %args) {
	my $future = Future::Uring::_Future->new;
	my (undef, $sourcename, $line) = caller;
	my $s_flags = %args ? to_sflags(\%args) : 0;
	my $flags = 0;
	$flags |= RENAME_EXCHANGE if $args{exchange};
	$flags |= RENAME_NOREPLACE if $args{no_replace};
	my $ring = ring;
	$ring->submit if $args{timeout} && $ring->sq_space_left < 2;
	my $id = $ring->renameat($args{old_base}, $old_path, $args{new_base}, $new_path, $flags, $s_flags, sub($res, $flags) {
		if ($res < 0) {
			$future->fail(Future::Uring::Exception->new('rename', $res, $sourcename, $line));
		} else {
			$future->done;
		}
	});
	$future->on_cancel(sub { $ring->cancel($id, 0, 0) }) if $args{mutable};
	add_timeout($ring, \%args) if $args{timeout};
	return $future;
}

sub rmdir($path, %args) {
	my $future = Future::Uring::_Future->new;
	my (undef, $sourcename, $line) = caller;
	my $s_flags = %args ? to_sflags(\%args) : 0;
	my $ring = ring;
	$ring->submit if $args{timeout} && $ring->sq_space_left < 2;
	my $id = $ring->unlinkat($args{base}, $path, AT_REMOVEDIR, $s_flags, sub($res, $flags) {
		if ($res < 0) {
			$future->fail(Future::Uring::Exception->new('rmdir', $res, $sourcename, $line));
		} else {
			$future->done;
		}
	});
	$future->on_cancel(sub { $ring->cancel($id, 0, 0) }) if $args{mutable};
	add_timeout($ring, \%args) if $args{timeout};
	return $future;
}

my %family_for = (
	inet   => AF_INET,
	inet6  => AF_INET6,
	unix   => AF_UNIX,
);

my %type_for = (
	stream    => SOCK_STREAM,
	datagram  => SOCK_DGRAM,
	seqpacket => SOCK_SEQPACKET,
	raw       => SOCK_RAW,
);

sub socket($family_name, %args) {
	my $future = Future::Uring::_Future->new;
	my (undef, $sourcename, $line) = caller;
	my $domain = $family_for{$family_name} // croak "No address family '$family_name' known";
	my $type = defined $args{type} ? $type_for{$args{type}} : SOCK_STREAM;
	my $protocol = defined $args{protocol} ? getprotobyname($args{protocol}) : 0;
	my $s_flags = %args ? to_sflags(\%args) : 0;
	my $ring = ring;
	$ring->submit if $args{timeout} && $ring->sq_space_left < 2;
	my $class = $args{class} // 'IO::Socket';
	my $id = $ring->socket($domain, $type, $protocol, $s_flags, sub($res, $flags) {
		if ($res >= 0) {
			my $fh = $class->new_from_fd($res);
			$future->done(Future::Uring::Handle->new($fh));
		} else {
			$future->fail(Future::Uring::Exception->new('socket', $res, $sourcename, $line));
		}
	});
	$future->on_cancel(sub { $ring->cancel($id, 0, 0) }) if $args{mutable};
	add_timeout($ring, \%args) if $args{timeout};
	return $future;
}

sub statx($path, %args) {
	my $future = Future::Uring::_Future->new;
	my (undef, $sourcename, $line) = caller;
	my $flags = $args{flags} // 0;
	my $mask = $args{mask} // STATX_BASIC_STATS | STATX_BTIME;
	my $stat = File::StatX->new;
	my $s_flags = %args ? to_sflags(\%args) : 0;
	my $ring = ring;
	$ring->submit if $args{timeout} && $ring->sq_space_left < 2;
	my $id = $ring->statx($args{base}, $path, $flags, $mask, $stat, $s_flags, sub($res, $flags) {
		if ($res >= 0) {
			$future->done($stat);
		} else {
			$future->fail(Future::Uring::Exception->new('statx', $res, $sourcename, $line));
		}
	});
	$future->on_cancel(sub { $ring->cancel($id, 0, 0) }) if $args{mutable};
	add_timeout($ring, \%args) if $args{timeout};
	return $future;
}

sub timeout_for($seconds, %args) {
	my $future = Future::Uring::_Future->new;
	my (undef, $sourcename, $line) = caller;
	my $time_spec = ref $seconds ? $seconds : Time::Spec->new($seconds);
	my $clock_id = $args{clock} ? $clocks{$args{clock}} // croak("No such clock $args{clock}") : 0;
	my $flags = $clock_id | IORING_TIMEOUT_ETIME_SUCCESS;



( run in 1.147 second using v1.01-cache-2.11-cpan-71847e10f99 )