package bgreader
import (
"io"
"sync"
"github.com/jackc/pgx/v5/internal/iobufpool"
)
const (
StatusStopped = iota
StatusRunning
StatusStopping
)
type BGReader struct {
r io .Reader
cond *sync .Cond
status int32
readResults []readResult
}
type readResult struct {
buf *[]byte
err error
}
func (r *BGReader ) Start () {
r .cond .L .Lock ()
defer r .cond .L .Unlock ()
switch r .status {
case StatusStopped :
r .status = StatusRunning
go r .bgRead ()
case StatusRunning :
case StatusStopping :
r .status = StatusRunning
}
}
func (r *BGReader ) Stop () {
r .cond .L .Lock ()
defer r .cond .L .Unlock ()
switch r .status {
case StatusStopped :
case StatusRunning :
r .status = StatusStopping
case StatusStopping :
}
}
func (r *BGReader ) Status () int32 {
r .cond .L .Lock ()
defer r .cond .L .Unlock ()
return r .status
}
func (r *BGReader ) bgRead () {
keepReading := true
for keepReading {
buf := iobufpool .Get (8192 )
n , err := r .r .Read (*buf )
*buf = (*buf )[:n ]
r .cond .L .Lock ()
r .readResults = append (r .readResults , readResult {buf : buf , err : err })
if r .status == StatusStopping || err != nil {
r .status = StatusStopped
keepReading = false
}
r .cond .L .Unlock ()
r .cond .Broadcast ()
}
}
func (r *BGReader ) Read (p []byte ) (int , error ) {
r .cond .L .Lock ()
defer r .cond .L .Unlock ()
if len (r .readResults ) > 0 {
return r .readFromReadResults (p )
}
if r .status == StatusStopped {
return r .r .Read (p )
}
for len (r .readResults ) == 0 {
r .cond .Wait ()
}
return r .readFromReadResults (p )
}
func (r *BGReader ) readFromReadResults (p []byte ) (int , error ) {
buf := r .readResults [0 ].buf
var err error
n := copy (p , *buf )
if n == len (*buf ) {
err = r .readResults [0 ].err
iobufpool .Put (buf )
if len (r .readResults ) == 1 {
r .readResults = nil
} else {
r .readResults = r .readResults [1 :]
}
} else {
*buf = (*buf )[n :]
r .readResults [0 ].buf = buf
}
return n , err
}
func New (r io .Reader ) *BGReader {
return &BGReader {
r : r ,
cond : &sync .Cond {
L : &sync .Mutex {},
},
}
}
The pages are generated with Golds v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .