github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/builtins/pipes/streams/define.go (about)

     1  package streams
     2  
     3  import (
     4  	"context"
     5  	"os"
     6  	"sync"
     7  	"sync/atomic"
     8  
     9  	"github.com/lmorg/murex/lang/stdio"
    10  )
    11  
    12  func init() {
    13  	stdio.RegisterPipe("std", newStream)
    14  }
    15  
    16  func newStream(_ string) (io stdio.Io, err error) {
    17  	io = NewStdin()
    18  	return
    19  }
    20  
    21  // Stdin is the default stdio.Io interface.
    22  // Despite it's name, this interface can and is used for Stdout and Stderr streams too.
    23  type Stdin struct {
    24  	mutex      sync.Mutex
    25  	ctx        context.Context
    26  	forceClose func()
    27  	buffer     []byte
    28  	bRead      uint64
    29  	bWritten   uint64
    30  	dependents int32
    31  	dataType   string
    32  	max        int
    33  }
    34  
    35  // DefaultMaxBufferSize is the maximum size of buffer for stdin
    36  // var DefaultMaxBufferSize = 1024 * 1024 * 1000 // 10 meg
    37  var DefaultMaxBufferSize = 1024 * 1024 * 1 // 1 meg
    38  
    39  // NewStdin creates a new stream.Io interface for piping data between processes.
    40  // Despite it's name, this interface can and is used for Stdout and Stderr streams too.
    41  func NewStdin() (stdin *Stdin) {
    42  	stdin = new(Stdin)
    43  	stdin.max = DefaultMaxBufferSize
    44  	//stdin.buffer = make([]byte, 0, 1024*1024)
    45  	stdin.ctx, stdin.forceClose = context.WithCancel(context.Background())
    46  	return
    47  }
    48  
    49  // NewStdinWithContext creates a new stream.Io interface for piping data between processes.
    50  // Despite it's name, this interface can and is used for Stdout and Stderr streams too.
    51  // This function is also useful as a context aware version of ioutil.ReadAll
    52  func NewStdinWithContext(ctx context.Context, forceClose context.CancelFunc) (stdin *Stdin) {
    53  	stdin = new(Stdin)
    54  	stdin.max = DefaultMaxBufferSize
    55  	stdin.ctx = ctx
    56  	stdin.forceClose = forceClose
    57  	return
    58  }
    59  
    60  func (stdin *Stdin) File() *os.File {
    61  	return nil
    62  }
    63  
    64  // Open the stream.Io interface for another dependant
    65  func (stdin *Stdin) Open() {
    66  	stdin.mutex.Lock()
    67  	atomic.AddInt32(&stdin.dependents, 1)
    68  	stdin.mutex.Unlock()
    69  }
    70  
    71  // Close the stream.Io interface
    72  func (stdin *Stdin) Close() {
    73  	stdin.mutex.Lock()
    74  
    75  	i := atomic.AddInt32(&stdin.dependents, -1)
    76  	if i < 0 {
    77  		panic("More closed dependents than open")
    78  	}
    79  
    80  	stdin.mutex.Unlock()
    81  }
    82  
    83  // ForceClose forces the stream.Io interface to close. This should only be called by a STDIN reader
    84  func (stdin *Stdin) ForceClose() {
    85  	if stdin.forceClose != nil {
    86  		stdin.forceClose()
    87  	}
    88  }