| @@ -16,39 +16,42 @@ limitations under the License. | ||||
|  | ||||
| package ioutil | ||||
|  | ||||
| import ( | ||||
| 	"io" | ||||
| 	"sync" | ||||
| ) | ||||
| import "io" | ||||
|  | ||||
| // writeCloseInformer wraps a reader with a close function. | ||||
| type wrapReadCloser struct { | ||||
| 	// TODO(random-liu): Evaluate whether the lock introduces | ||||
| 	// performance regression. | ||||
| 	sync.RWMutex | ||||
| 	r      io.Reader | ||||
| 	closed bool | ||||
| 	reader *io.PipeReader | ||||
| 	writer *io.PipeWriter | ||||
| } | ||||
|  | ||||
| // NewWrapReadCloser creates a wrapReadCloser from a reader. | ||||
| // NOTE(random-liu): To avoid goroutine leakage, the reader passed in | ||||
| // must be eventually closed by the caller. | ||||
| func NewWrapReadCloser(r io.Reader) io.ReadCloser { | ||||
| 	return &wrapReadCloser{r: r} | ||||
| 	pr, pw := io.Pipe() | ||||
| 	go func() { | ||||
| 		_, _ = io.Copy(pw, r) | ||||
| 		pr.Close() | ||||
| 		pw.Close() | ||||
| 	}() | ||||
| 	return &wrapReadCloser{ | ||||
| 		reader: pr, | ||||
| 		writer: pw, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Read reads up to len(p) bytes into p. | ||||
| func (w *wrapReadCloser) Read(p []byte) (int, error) { | ||||
| 	w.RLock() | ||||
| 	defer w.RUnlock() | ||||
| 	if w.closed { | ||||
| 		return 0, io.EOF | ||||
| 	n, err := w.reader.Read(p) | ||||
| 	if err == io.ErrClosedPipe { | ||||
| 		return n, io.EOF | ||||
| 	} | ||||
| 	return w.r.Read(p) | ||||
| 	return n, err | ||||
| } | ||||
|  | ||||
| // Close closes read closer. | ||||
| func (w *wrapReadCloser) Close() error { | ||||
| 	w.Lock() | ||||
| 	defer w.Unlock() | ||||
| 	w.closed = true | ||||
| 	w.reader.Close() | ||||
| 	w.writer.Close() | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Lantao Liu
					Lantao Liu