github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/internal/bpool/bpool.go (about) 1 // Copyright (c) 2015-2023 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package bpool 19 20 import "github.com/klauspost/reedsolomon" 21 22 // BytePoolCap implements a leaky pool of []byte in the form of a bounded channel. 23 type BytePoolCap struct { 24 c chan []byte 25 w int 26 wcap int 27 } 28 29 // NewBytePoolCap creates a new BytePool bounded to the given maxSize, with new 30 // byte arrays sized based on width. 31 func NewBytePoolCap(maxSize uint64, width int, capwidth int) (bp *BytePoolCap) { 32 if capwidth > 0 && capwidth < 64 { 33 panic("buffer capped with smaller than 64 bytes is not supported") 34 } 35 if capwidth > 0 && width > capwidth { 36 panic("buffer length cannot be > capacity of the buffer") 37 } 38 return &BytePoolCap{ 39 c: make(chan []byte, maxSize), 40 w: width, 41 wcap: capwidth, 42 } 43 } 44 45 // Populate - populates and pre-warms the byte pool, this function is non-blocking. 46 func (bp *BytePoolCap) Populate() { 47 for _, buf := range reedsolomon.AllocAligned(cap(bp.c), bp.wcap) { 48 bp.Put(buf[:bp.w]) 49 } 50 } 51 52 // Get gets a []byte from the BytePool, or creates a new one if none are 53 // available in the pool. 54 func (bp *BytePoolCap) Get() (b []byte) { 55 select { 56 case b = <-bp.c: 57 // reuse existing buffer 58 default: 59 // create new aligned buffer 60 if bp.wcap > 0 { 61 b = reedsolomon.AllocAligned(1, bp.wcap)[0][:bp.w] 62 } else { 63 b = reedsolomon.AllocAligned(1, bp.w)[0] 64 } 65 } 66 return 67 } 68 69 // Put returns the given Buffer to the BytePool. 70 func (bp *BytePoolCap) Put(b []byte) { 71 select { 72 case bp.c <- b: 73 // buffer went back into pool 74 default: 75 // buffer didn't go back into pool, just discard 76 } 77 } 78 79 // Width returns the width of the byte arrays in this pool. 80 func (bp *BytePoolCap) Width() (n int) { 81 return bp.w 82 } 83 84 // WidthCap returns the cap width of the byte arrays in this pool. 85 func (bp *BytePoolCap) WidthCap() (n int) { 86 return bp.wcap 87 }