1package quic 2 3import ( 4 "sync" 5 6 "github.com/lucas-clemente/quic-go/internal/protocol" 7) 8 9type packetBuffer struct { 10 Data []byte 11 12 // refCount counts how many packets Data is used in. 13 // It doesn't support concurrent use. 14 // It is > 1 when used for coalesced packet. 15 refCount int 16} 17 18// Split increases the refCount. 19// It must be called when a packet buffer is used for more than one packet, 20// e.g. when splitting coalesced packets. 21func (b *packetBuffer) Split() { 22 b.refCount++ 23} 24 25// Decrement decrements the reference counter. 26// It doesn't put the buffer back into the pool. 27func (b *packetBuffer) Decrement() { 28 b.refCount-- 29 if b.refCount < 0 { 30 panic("negative packetBuffer refCount") 31 } 32} 33 34// MaybeRelease puts the packet buffer back into the pool, 35// if the reference counter already reached 0. 36func (b *packetBuffer) MaybeRelease() { 37 // only put the packetBuffer back if it's not used any more 38 if b.refCount == 0 { 39 b.putBack() 40 } 41} 42 43// Release puts back the packet buffer into the pool. 44// It should be called when processing is definitely finished. 45func (b *packetBuffer) Release() { 46 b.Decrement() 47 if b.refCount != 0 { 48 panic("packetBuffer refCount not zero") 49 } 50 b.putBack() 51} 52 53// Len returns the length of Data 54func (b *packetBuffer) Len() protocol.ByteCount { 55 return protocol.ByteCount(len(b.Data)) 56} 57 58func (b *packetBuffer) putBack() { 59 if cap(b.Data) != int(protocol.MaxPacketBufferSize) { 60 panic("putPacketBuffer called with packet of wrong size!") 61 } 62 bufferPool.Put(b) 63} 64 65var bufferPool sync.Pool 66 67func getPacketBuffer() *packetBuffer { 68 buf := bufferPool.Get().(*packetBuffer) 69 buf.refCount = 1 70 buf.Data = buf.Data[:0] 71 return buf 72} 73 74func init() { 75 bufferPool.New = func() interface{} { 76 return &packetBuffer{ 77 Data: make([]byte, 0, protocol.MaxPacketBufferSize), 78 } 79 } 80} 81