103 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			103 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| /*
 | |
|    Copyright The containerd Authors.
 | |
| 
 | |
|    Licensed under the Apache License, Version 2.0 (the "License");
 | |
|    you may not use this file except in compliance with the License.
 | |
|    You may obtain a copy of the License at
 | |
| 
 | |
|        http://www.apache.org/licenses/LICENSE-2.0
 | |
| 
 | |
|    Unless required by applicable law or agreed to in writing, software
 | |
|    distributed under the License is distributed on an "AS IS" BASIS,
 | |
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
|    See the License for the specific language governing permissions and
 | |
|    limitations under the License.
 | |
| */
 | |
| 
 | |
| package ioutil
 | |
| 
 | |
| import (
 | |
| 	"io"
 | |
| 	"sync"
 | |
| )
 | |
| 
 | |
| // writeCloseInformer wraps passed in write closer with a close channel.
 | |
| // Caller could wait on the close channel for the write closer to be
 | |
| // closed.
 | |
| type writeCloseInformer struct {
 | |
| 	close chan struct{}
 | |
| 	wc    io.WriteCloser
 | |
| }
 | |
| 
 | |
| // NewWriteCloseInformer creates the writeCloseInformer from a write closer.
 | |
| func NewWriteCloseInformer(wc io.WriteCloser) (io.WriteCloser, <-chan struct{}) {
 | |
| 	close := make(chan struct{})
 | |
| 	return &writeCloseInformer{
 | |
| 		close: close,
 | |
| 		wc:    wc,
 | |
| 	}, close
 | |
| }
 | |
| 
 | |
| // Write passes through the data into the internal write closer.
 | |
| func (w *writeCloseInformer) Write(p []byte) (int, error) {
 | |
| 	return w.wc.Write(p)
 | |
| }
 | |
| 
 | |
| // Close closes the internal write closer and inform the close channel.
 | |
| func (w *writeCloseInformer) Close() error {
 | |
| 	err := w.wc.Close()
 | |
| 	close(w.close)
 | |
| 	return err
 | |
| }
 | |
| 
 | |
| // nopWriteCloser wraps passed in writer with a nop close function.
 | |
| type nopWriteCloser struct {
 | |
| 	w io.Writer
 | |
| }
 | |
| 
 | |
| // NewNopWriteCloser creates the nopWriteCloser from a writer.
 | |
| func NewNopWriteCloser(w io.Writer) io.WriteCloser {
 | |
| 	return &nopWriteCloser{w: w}
 | |
| }
 | |
| 
 | |
| // Write passes through the data into the internal writer.
 | |
| func (n *nopWriteCloser) Write(p []byte) (int, error) {
 | |
| 	return n.w.Write(p)
 | |
| }
 | |
| 
 | |
| // Close is a nop close function.
 | |
| func (n *nopWriteCloser) Close() error {
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // serialWriteCloser wraps a write closer and makes sure all writes
 | |
| // are done in serial.
 | |
| // Parallel write won't intersect with each other. Use case:
 | |
| //  1. Pipe: Write content longer than PIPE_BUF.
 | |
| //     See http://man7.org/linux/man-pages/man7/pipe.7.html
 | |
| //  2. <3.14 Linux Kernel: write is not atomic
 | |
| //     See http://man7.org/linux/man-pages/man2/write.2.html
 | |
| type serialWriteCloser struct {
 | |
| 	mu sync.Mutex
 | |
| 	wc io.WriteCloser
 | |
| }
 | |
| 
 | |
| // NewSerialWriteCloser creates a SerialWriteCloser from a write closer.
 | |
| func NewSerialWriteCloser(wc io.WriteCloser) io.WriteCloser {
 | |
| 	return &serialWriteCloser{wc: wc}
 | |
| }
 | |
| 
 | |
| // Write writes a group of byte arrays in order atomically.
 | |
| func (s *serialWriteCloser) Write(data []byte) (int, error) {
 | |
| 	s.mu.Lock()
 | |
| 	defer s.mu.Unlock()
 | |
| 	return s.wc.Write(data)
 | |
| }
 | |
| 
 | |
| // Close closes the write closer.
 | |
| func (s *serialWriteCloser) Close() error {
 | |
| 	s.mu.Lock()
 | |
| 	defer s.mu.Unlock()
 | |
| 	return s.wc.Close()
 | |
| }
 | 
