mirror of
https://github.com/slackhq/nebula.git
synced 2026-06-30 18:40:29 +02:00
40 lines
1.3 KiB
Go
40 lines
1.3 KiB
Go
package util
|
|
|
|
// Arena is an injectable byte-slab that hands out non-overlapping borrowed
|
|
// slices via Reserve and releases them in bulk via Reset.
|
|
//
|
|
// Arena is not safe for concurrent use.
|
|
//
|
|
// Reserve borrows; the slice is valid until the next Reset. The slab grows
|
|
// (by allocating a fresh, larger backing array) if a Reserve doesn't fit;
|
|
// pre-size the arena via NewArena to avoid that path on the hot path.
|
|
type Arena struct {
|
|
buf []byte
|
|
}
|
|
|
|
// NewArena returns an Arena with a pre-allocated backing of the given capacity
|
|
func NewArena(capacity int) *Arena {
|
|
return &Arena{buf: make([]byte, 0, capacity)}
|
|
}
|
|
|
|
// Reserve hands out a non-overlapping sz-byte slice from the arena. If the
|
|
// request doesn't fit the current backing, a fresh, larger backing is
|
|
// allocated; already-borrowed slices reference the old backing and remain
|
|
// valid until Reset.
|
|
func (a *Arena) Reserve(sz int) []byte {
|
|
if len(a.buf)+sz > cap(a.buf) {
|
|
newCap := max(cap(a.buf)*2, sz)
|
|
a.buf = make([]byte, 0, newCap)
|
|
}
|
|
start := len(a.buf)
|
|
a.buf = a.buf[:start+sz]
|
|
return a.buf[start : start+sz : start+sz]
|
|
}
|
|
|
|
// Reset releases every slice handed out since the last Reset. Callers must
|
|
// not use any previously-borrowed slice after this returns. The underlying
|
|
// backing array is retained so subsequent Reserves don't re-allocate.
|
|
func (a *Arena) Reset() {
|
|
a.buf = a.buf[:0]
|
|
}
|