bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Examples of concurrent coproc usage?


From: Martin D Kealey
Subject: Re: Examples of concurrent coproc usage?
Date: Thu, 18 Apr 2024 12:55:08 +1200 (NZST)
User-agent: Alpine 2.21 (DEB 202 2017-01-01)

On Wed, 17 Apr 2024, Chet Ramey wrote:
> On 4/16/24 2:46 AM, Carl Edquist wrote:
>
> > But the shell is pretty slow when you ask it to shovel data around like
> > this.  The 'read' builtin, for instance, cautiously does read(2) calls of a
> > single byte at a time.
>
> It has to do it that way to find the delimiter on a non-seekable file
> descriptor, since it has to leave everything it didn't consume available
> on stdin.

Has anyone tried asking any of the kernel teams (Linux, BSD, or other) to
add a new system call such as readln() or readd()?

I envisage this working like stty cooked mode works on a tty, except it
would also work on files, pipes, and sockets: you'd get back *at most* as
many bytes as you ask for, but you may get fewer if a delimiter is found.
The delimiter is consumed (and returned in the buffer), but everything
following a delimiter is left available for a subsequent read.

For a tty, code like

 tc_setattr(fd, &(struct termios){ .c_iflags = ICANON, .c_cc = { [EOL] = '\n' 
}});
 ssize_t n = read(fd, &buf, sizeof buf);

could become just

 ssize_t n = readd(fd, &buf, sizeof buf, "\n", 1, 0 /*flags*/);

or perhaps even

 ssize_t n = readdv(fd,
                    &buf, sizeof buf,
                    (struct iovec[]){{"\n", 1}}, 1,
                    0 /*flags*/);

I'm not sure whether multi-byte delimiters should be allowed, as it's
unclear what to do when you get an incomplete delimiter at the end of the
buffer, but an iovec interface would at least allow that as a future
possibility.

As Linux kernel developers have found, it's better to *always* include a
flags argument, even if you can't think of a use for it yet; but in this
case O_NONBLOCK and O_PEEK could immediately be useful.

-Martin

PS: I initially wondered about having

 ssize_t n = readvdv(fd,
                     (struct iovec[]){{&buf, sizeof buf}}, 1,
                     (struct iovec[]){{"\n", 1}}, 1);

but a vectored read isn't much of a saving unless the overall size is very
large, and enormous reads probably shouldn't use this facility since the
in-kernel byte scan would potentially block reads and writes by other
processes.

For the same reason I would allow the read size to be silently capped at a
value chosen by the kernel, probably a small multiple (1?) of the IO block
size or the pipe buffer size or the tty input buffer size.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]