NAME
Future::Buffer
- a string buffer that uses Futures
SYNOPSIS
use Future::Buffer;
use Future::AsyncAwait;
use Future::IO;
my $buffer = Future::Buffer->new(
fill => sub { Future::IO->sysread( $socket, 8192 ) }
);
async sub print_lines
{
while(1) {
my $line = await $buffer->read_until( "\n" );
chomp $line;
say "Got a line: $line";
}
}
print_lines()->get;
DESCRIPTION
Objects in this class provide a string buffer, on which operations return Future instances which will complete when data is available. Data can be inserted into the buffer either in a push-based manner by calling the write
method, or in a pull-based manner by providing it with a fill
callback by which it can request data itself. This flexibility allows the buffer to act as an adapter between push- and pull-based providers and consumers.
Each read
-like method returns a Future which will complete once there are enough bytes in the buffer to satisfy the required condition. The buffer behaves somewhat like a pipe, where bytes provided at the writing end (either by the write
method or the fill
callback) are eventually consumed at the reading end by one of the read
futures.
Multiple read
futures can remain pending at once, and will be completed in the order they were created when more data is eventually available. Thus, any call to the write
method to provide more data can potentially result in multiple futures becoming ready.
CONSTRUCTOR
new
$buffer = Future::Buffer->new( %args )
Returns a new Future::Buffer instance.
Takes the following named arguments:
- fill => CODE
-
$f = $fill->() $data = $f->get
Optional callback which the buffer will invoke when it needs more data.
Any read futures which are waiting on the fill future are constructed by using the fill future as a prototype, ensuring they have the correct type.
METHODS
length
$len = $buffer->length
Returns the length of the currently-stored data; that is, data that has been provided by write
calls but not yet consumed by read
.
is_empty
$empty = $buffer->is_empty
Returns true if the stored length is zero.
write
$f = $buffer->write( $data )
Appends to the stored data, invoking any pending read
futures that are outstanding and can now complete.
Currently this method returns an already-completed Future
. Some later version may implement a buffer maximum size, and choose not to complete this future until there is enough space to accept the new data. For now it is safe for the caller to ignore the return value, but it may become not so.
read
$f = $buffer->read( $len )
$data = $f->get
Returns a future which will complete when there is some data available in the buffer and will yield up too the given length. Note that, analogous to calling the read
IO method on a filehandle, this can still complete and yield a shorter length if less is currently available.
read_exactly
$f = $buffer->read_exactly( $len )
$data = $f->get
Returns a future which will complete when there is enough data available in the buffer to yield exactly the length given.
read_until
$f = $buffer->read_until( $pattern )
$data = $f->get
Returns a future which will complete when the buffer contains a match for the given pattern (which may either be a plain string or a compiled Regexp
). The future will yield the contents of the buffer up to and including this match.
For example, a readline
-like operation can be performed by
$f = $buffer->read_until( "\x0d\x0a" );
TODO
An "on-read" event, taking maybe inspiration from IO::Async::Stream. This would allow both pull- and push-based consumers.
Size limitation. Allow an upper bound of stored data, make
write
calls return pending futures until buffer can accept it. Needs consideration of unboundedread_until
though.Consider some
read + unpack
assistance, to allow nice handling of binary protocols by unpacking out of the buffer directly.Consider what happens at EOF. Add a
close
method for producers to call. Understand whatfill
would do there. Have all the pendingread
futures yield an empty list maybe?
AUTHOR
Paul Evans <leonerd@leonerd.org.uk>
Inspired by Ryu::Buffer by Tom Molesworth <TEAM@cpan.org>