123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- package gfsmux
- import (
- "errors"
- "sync"
- )
- var (
- defaultAllocator *Allocator
- debruijinPos = [...]byte{0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31}
- )
- func init() {
- defaultAllocator = NewAllocator()
- }
- // Allocator for incoming frames, optimized to prevent overwriting after zeroing
- type Allocator struct {
- buffers []sync.Pool
- }
- // NewAllocator initiates a []byte allocator for frames less than 65536 bytes,
- // the waste(memory fragmentation) of space allocation is guaranteed to be
- // no more than 50%.
- func NewAllocator() *Allocator {
- alloc := new(
- Allocator,
- )
- alloc.buffers = make(
- []sync.Pool,
- 17,
- ) // 1B -> 64K
- for k := range alloc.buffers {
- i := k
- alloc.buffers[k].New = func() interface{} {
- return make(
- []byte,
- 1<<uint32(
- i,
- ),
- )
- }
- }
- return alloc
- }
- // Get a []byte from pool with most appropriate cap
- func (
- alloc *Allocator,
- ) Get(
- size int,
- ) []byte {
- if size <= 0 || size > 65536 {
- return nil
- }
- bits := Smsb(
- size,
- )
- if size == 1<<bits {
- return alloc.buffers[bits].Get().([]byte)[:size]
- }
- return alloc.buffers[bits+1].Get().([]byte)[:size]
- }
- // Put returns a []byte to pool for future use,
- // which the cap must be exactly 2^n
- func (
- alloc *Allocator,
- ) Put(
- buf []byte,
- ) error {
- bits := Smsb(
- cap(
- buf,
- ),
- )
- if cap(
- buf,
- ) == 0 || cap(
- buf,
- ) > 65536 || cap(
- buf,
- ) != 1<<bits {
- return errors.New(
- "allocator Put() incorrect buffer size",
- )
- }
- alloc.buffers[bits].Put(
- buf,
- )
- return nil
- }
- // Smsb returns the position of most significiant bit
- // http://supertech.csail.mit.edu/papers/debruijn.pdf
- func Smsb(
- size int,
- ) byte {
- v := uint32(size)
- v |= v >> 1
- v |= v >> 2
- v |= v >> 4
- v |= v >> 8
- v |= v >> 16
- return debruijinPos[(v*0x07C4ACDD)>>27]
- }
|