1
0
mirror of https://github.com/golang/go synced 2024-11-23 16:30:06 -07:00

archive/zip: clarify expectations of RegisterCompressor and RegisterDecompressor

Clarify that Compressor and Decompressor callbacks must support being invoked
concurrently, but that the writer or reader returned need not be.

Updates #8359

Change-Id: Ia407b581dd124185f165c25f5701018a8ce4357a
Reviewed-on: https://go-review.googlesource.com/18627
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Joe Tsai 2016-01-14 00:38:48 -08:00 committed by Brad Fitzpatrick
parent 1d901f55bd
commit c736280e22
3 changed files with 18 additions and 26 deletions

View File

@ -76,8 +76,7 @@ func ExampleReader() {
} }
func ExampleWriter_RegisterCompressor() { func ExampleWriter_RegisterCompressor() {
// Override the default Deflate compressor with a higher compression // Override the default Deflate compressor with a higher compression level.
// level.
// Create a buffer to write our archive to. // Create a buffer to write our archive to.
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
@ -85,19 +84,9 @@ func ExampleWriter_RegisterCompressor() {
// Create a new zip archive. // Create a new zip archive.
w := zip.NewWriter(buf) w := zip.NewWriter(buf)
var fw *flate.Writer // Register a custom Deflate compressor.
// Register the deflator.
w.RegisterCompressor(zip.Deflate, func(out io.Writer) (io.WriteCloser, error) { w.RegisterCompressor(zip.Deflate, func(out io.Writer) (io.WriteCloser, error) {
var err error return flate.NewWriter(out, flate.BestCompression)
if fw == nil {
// Creating a flate compressor for every file is
// expensive, create one and reuse it.
fw, err = flate.NewWriter(out, flate.BestCompression)
} else {
fw.Reset(out)
}
return fw, err
}) })
// Proceed to add files to w. // Proceed to add files to w.

View File

@ -118,8 +118,6 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
// RegisterDecompressor registers or overrides a custom decompressor for a // RegisterDecompressor registers or overrides a custom decompressor for a
// specific method ID. If a decompressor for a given method is not found, // specific method ID. If a decompressor for a given method is not found,
// Reader will default to looking up the decompressor at the package level. // Reader will default to looking up the decompressor at the package level.
//
// Must not be called concurrently with Open on any Files in the Reader.
func (z *Reader) RegisterDecompressor(method uint16, dcomp Decompressor) { func (z *Reader) RegisterDecompressor(method uint16, dcomp Decompressor) {
if z.decompressors == nil { if z.decompressors == nil {
z.decompressors = make(map[uint16]Decompressor) z.decompressors = make(map[uint16]Decompressor)

View File

@ -12,15 +12,19 @@ import (
"sync" "sync"
) )
// A Compressor returns a compressing writer, writing to the // A Compressor returns a new compressing writer, writing to w.
// provided writer. On Close, any pending data should be flushed. // The WriteCloser's Close method must be used to flush pending data to w.
type Compressor func(io.Writer) (io.WriteCloser, error) // The Compressor itself must be safe to invoke from multiple goroutines
// simultaneously, but each returned writer will be used only by
// one goroutine at a time.
type Compressor func(w io.Writer) (io.WriteCloser, error)
// Decompressor is a function that wraps a Reader with a decompressing Reader. // A Decompressor returns a new decompressing reader, reading from r.
// The decompressed ReadCloser is returned to callers who open files from // The ReadCloser's Close method must be used to release associated resources.
// within the archive. These callers are responsible for closing this reader // The Decompressor itself must be safe to invoke from multiple goroutines
// when they're finished reading. // simultaneously, but each returned reader will be used only by
type Decompressor func(io.Reader) io.ReadCloser // one goroutine at a time.
type Decompressor func(r io.Reader) io.ReadCloser
var flateWriterPool sync.Pool var flateWriterPool sync.Pool
@ -75,14 +79,15 @@ var (
) )
// RegisterDecompressor allows custom decompressors for a specified method ID. // RegisterDecompressor allows custom decompressors for a specified method ID.
func RegisterDecompressor(method uint16, d Decompressor) { // The common methods Store and Deflate are built in.
func RegisterDecompressor(method uint16, dcomp Decompressor) {
mu.Lock() mu.Lock()
defer mu.Unlock() defer mu.Unlock()
if _, ok := decompressors[method]; ok { if _, ok := decompressors[method]; ok {
panic("decompressor already registered") panic("decompressor already registered")
} }
decompressors[method] = d decompressors[method] = dcomp
} }
// RegisterCompressor registers custom compressors for a specified method ID. // RegisterCompressor registers custom compressors for a specified method ID.