2
0

Add PgConn.SyncConn

This provides a way to ensure it is safe to directly read or write to
the underlying net.Conn.

https://github.com/jackc/pgx/issues/1673
This commit is contained in:
Jack Christensen
2023-07-08 16:46:38 -05:00
committed by Jack Christensen
parent 05440f9d3f
commit f512b9688b
4 changed files with 63 additions and 24 deletions
+27 -20
View File
@@ -9,18 +9,18 @@ import (
)
const (
bgReaderStatusStopped = iota
bgReaderStatusRunning
bgReaderStatusStopping
StatusStopped = iota
StatusRunning
StatusStopping
)
// BGReader is an io.Reader that can optionally buffer reads in the background. It is safe for concurrent use.
type BGReader struct {
r io.Reader
cond *sync.Cond
bgReaderStatus int32
readResults []readResult
cond *sync.Cond
status int32
readResults []readResult
}
type readResult struct {
@@ -34,14 +34,14 @@ func (r *BGReader) Start() {
r.cond.L.Lock()
defer r.cond.L.Unlock()
switch r.bgReaderStatus {
case bgReaderStatusStopped:
r.bgReaderStatus = bgReaderStatusRunning
switch r.status {
case StatusStopped:
r.status = StatusRunning
go r.bgRead()
case bgReaderStatusRunning:
case StatusRunning:
// no-op
case bgReaderStatusStopping:
r.bgReaderStatus = bgReaderStatusRunning
case StatusStopping:
r.status = StatusRunning
}
}
@@ -51,16 +51,23 @@ func (r *BGReader) Stop() {
r.cond.L.Lock()
defer r.cond.L.Unlock()
switch r.bgReaderStatus {
case bgReaderStatusStopped:
switch r.status {
case StatusStopped:
// no-op
case bgReaderStatusRunning:
r.bgReaderStatus = bgReaderStatusStopping
case bgReaderStatusStopping:
case StatusRunning:
r.status = StatusStopping
case StatusStopping:
// no-op
}
}
// Status returns the current status of the background reader.
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 {
@@ -70,8 +77,8 @@ func (r *BGReader) bgRead() {
r.cond.L.Lock()
r.readResults = append(r.readResults, readResult{buf: buf, err: err})
if r.bgReaderStatus == bgReaderStatusStopping || err != nil {
r.bgReaderStatus = bgReaderStatusStopped
if r.status == StatusStopping || err != nil {
r.status = StatusStopped
keepReading = false
}
r.cond.L.Unlock()
@@ -89,7 +96,7 @@ func (r *BGReader) Read(p []byte) (int, error) {
}
// There are no unread background read results and the background reader is stopped.
if r.bgReaderStatus == bgReaderStatusStopped {
if r.status == StatusStopped {
return r.r.Read(p)
}