github.com/markusbkk/elvish@v0.0.0-20231204143114-91dc52438621/pkg/sys/eunix/waitforread.go (about)

     1  //go:build !windows && !plan9
     2  // +build !windows,!plan9
     3  
     4  package eunix
     5  
     6  import (
     7  	"os"
     8  	"time"
     9  
    10  	"golang.org/x/sys/unix"
    11  )
    12  
    13  // WaitForRead blocks until any of the given files is ready to be read or
    14  // timeout. A negative timeout means no timeout. It returns a boolean array
    15  // indicating which files are ready to be read and any possible error.
    16  func WaitForRead(timeout time.Duration, files ...*os.File) (ready []bool, err error) {
    17  	maxfd := 0
    18  	fdset := &unix.FdSet{}
    19  	for _, file := range files {
    20  		fd := int(file.Fd())
    21  		if maxfd < fd {
    22  			maxfd = fd
    23  		}
    24  		fdset.Set(fd)
    25  	}
    26  	_, err = unix.Select(maxfd+1, fdset, nil, nil, optionalTimeval(timeout))
    27  	ready = make([]bool, len(files))
    28  	for i, file := range files {
    29  		ready[i] = fdset.IsSet(int(file.Fd()))
    30  	}
    31  	return ready, err
    32  }
    33  
    34  func optionalTimeval(d time.Duration) *unix.Timeval {
    35  	if d < 0 {
    36  		return nil
    37  	}
    38  	timeval := unix.NsecToTimeval(int64(d))
    39  	return &timeval
    40  }