64 lines
1.2 KiB
Go
64 lines
1.2 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
// Package iosync provides reader/writer implementations that wrap
|
|
// operations in a mutex so that concurrent reads and writes are safe.
|
|
package iosync
|
|
|
|
import (
|
|
"io"
|
|
"sync"
|
|
)
|
|
|
|
// ReadWriter returns an io.ReadWriter where reading/writing concurrently is
|
|
// safe. Both read/write operations will share the same mutex. All operations
|
|
// are exclusive. We do not use a RWMutex because most io.Readers aren't
|
|
// inherently safe to concurrent read access.
|
|
func ReadWriter(rw io.ReadWriter) io.ReadWriter {
|
|
var m sync.Mutex
|
|
return &readWriter{
|
|
Reader: &reader{
|
|
Mutex: &m,
|
|
Reader: rw,
|
|
},
|
|
|
|
Writer: &writer{
|
|
Mutex: &m,
|
|
Writer: rw,
|
|
},
|
|
}
|
|
}
|
|
|
|
type readWriter struct {
|
|
io.Reader
|
|
io.Writer
|
|
}
|
|
|
|
type writer struct {
|
|
*sync.Mutex
|
|
io.Writer
|
|
}
|
|
|
|
func (w *writer) Write(p []byte) (int, error) {
|
|
w.Lock()
|
|
defer w.Unlock()
|
|
return w.Writer.Write(p)
|
|
}
|
|
|
|
type reader struct {
|
|
*sync.Mutex
|
|
io.Reader
|
|
}
|
|
|
|
func (r *reader) Read(p []byte) (int, error) {
|
|
r.Lock()
|
|
defer r.Unlock()
|
|
return r.Reader.Read(p)
|
|
}
|
|
|
|
var (
|
|
_ io.Reader = (*reader)(nil)
|
|
_ io.Writer = (*writer)(nil)
|
|
_ io.ReadWriter = (*readWriter)(nil)
|
|
)
|