GetN get n buffers atomically from the pool or allocate them
(n int)
| 227 | |
| 228 | // GetN get n buffers atomically from the pool or allocate them |
| 229 | func (bp *Pool) GetN(n int) [][]byte { |
| 230 | bp.mu.Lock() |
| 231 | var ( |
| 232 | waitTime = time.Millisecond // retry time if allocation failed |
| 233 | err error // allocation error |
| 234 | buf []byte // allocated buffer |
| 235 | bufs [][]byte // bufs so far |
| 236 | have int // have this many buffers in bp.cache |
| 237 | want int // want this many extra buffers |
| 238 | acquired bool // whether we have acquired the memory or not |
| 239 | ) |
| 240 | for { |
| 241 | acquired = false |
| 242 | bp.mu.Unlock() |
| 243 | err = bp.acquire(int64(bp.bufferSize) * int64(n)) |
| 244 | bp.mu.Lock() |
| 245 | if err != nil { |
| 246 | goto FAIL |
| 247 | } |
| 248 | acquired = true |
| 249 | have = min(bp.buffers(), n) |
| 250 | want = n - have |
| 251 | bufs = bp.getN(have) // get as many buffers as we have from the cache |
| 252 | for range want { |
| 253 | buf, err = bp.alloc(bp.bufferSize) |
| 254 | if err != nil { |
| 255 | goto FAIL |
| 256 | } |
| 257 | bp.alloced++ |
| 258 | bufs = append(bufs, buf) |
| 259 | } |
| 260 | break |
| 261 | FAIL: |
| 262 | // Release the buffers and the allocation if it succeeded |
| 263 | bp.putN(bufs) |
| 264 | if acquired { |
| 265 | bp.release(int64(bp.bufferSize) * int64(n)) |
| 266 | } |
| 267 | fs.Logf(nil, "Failed to get memory for buffer, waiting for %v: %v", waitTime, err) |
| 268 | bp.mu.Unlock() |
| 269 | time.Sleep(waitTime) |
| 270 | bp.mu.Lock() |
| 271 | waitTime *= 2 |
| 272 | clear(bufs) |
| 273 | bufs = nil |
| 274 | } |
| 275 | bp.inUse += n |
| 276 | bp.updateMinFill() |
| 277 | bp.mu.Unlock() |
| 278 | return bufs |
| 279 | } |
| 280 | |
| 281 | // freeBuffer returns mem to the os if required - call with lock held |
| 282 | func (bp *Pool) freeBuffer(mem []byte) { |