No decoder goroutines (test)
diff --git a/zstd/decoder.go b/zstd/decoder.go index f593e46..185f98d 100644 --- a/zstd/decoder.go +++ b/zstd/decoder.go
@@ -97,10 +97,12 @@ // Create decoders d.decoders = make(chan *blockDec, d.o.concurrent) - for i := 0; i < d.o.concurrent; i++ { - dec := newBlockDec(d.o.lowMem) - dec.localFrame = newFrameDec(d.o) - d.decoders <- dec + if d.o.async { + for i := 0; i < d.o.concurrent; i++ { + dec := newBlockDec(d.o.lowMem) + dec.localFrame = newFrameDec(d.o) + d.decoders <- dec + } } if r == nil { @@ -202,6 +204,14 @@ return nil } + if !d.o.async { + for i := 0; i < d.o.concurrent; i++ { + dec := newBlockDec(d.o.lowMem) + dec.localFrame = newFrameDec(d.o) + d.decoders <- dec + } + } + // Remove current block. d.current.decodeOutput = decodeOutput{} d.current.err = nil @@ -249,6 +259,28 @@ return } } + + // Drain... + if !d.o.async { + if d.stream != nil { + close(d.stream) + } + for i := 0; i < d.o.concurrent; i++ { + select { + case dec := <-d.decoders: + dec.Close() + default: + } + } + if d.stream != nil { + d.streamWg.Wait() + d.stream = nil + } + if d.current.d != nil { + d.current.d.Close() + d.current.d = nil + } + } } // WriteTo writes data to w until there's no more data to write or when an error occurs.
diff --git a/zstd/decoder_options.go b/zstd/decoder_options.go index c0fd058..156b1bd 100644 --- a/zstd/decoder_options.go +++ b/zstd/decoder_options.go
@@ -15,6 +15,7 @@ // options retains accumulated state of multiple options. type decoderOptions struct { lowMem bool + async bool concurrent int maxDecodedSize uint64 dicts []dict @@ -25,10 +26,18 @@ // use less ram: true for now, but may change. lowMem: true, concurrent: runtime.GOMAXPROCS(0), + async: true, } o.maxDecodedSize = 1 << 63 } +func (o *decoderOptions) finalize() error { + if o.lowMem && o.concurrent == 1 { + o.async = false + } + return nil +} + // WithDecoderLowmem will set whether to use a lower amount of memory, // but possibly have to allocate more while running. func WithDecoderLowmem(b bool) DOption {