68 lines
1.2 KiB
Go
68 lines
1.2 KiB
Go
package pools
|
|
|
|
import "sync"
|
|
|
|
// StringPool is a pool for strings.
|
|
// This will most likely be a pool for IP addresses.
|
|
type StringPool struct {
|
|
values map[string]*string
|
|
|
|
counter map[string]uint
|
|
top uint
|
|
|
|
sync.RWMutex
|
|
}
|
|
|
|
// NewStringPool creates a new string pool
|
|
func NewStringPool() *StringPool {
|
|
return &StringPool{
|
|
values: map[string]*string{},
|
|
counter: map[string]uint{},
|
|
}
|
|
}
|
|
|
|
// Acquire a pointer to a string value
|
|
func (p *StringPool) Acquire(s string) *string {
|
|
p.Lock()
|
|
defer p.Unlock()
|
|
// Deduplicate value
|
|
ptr, ok := p.values[s]
|
|
if !ok {
|
|
p.values[s] = &s
|
|
ptr = &s
|
|
}
|
|
p.counter[s] = p.top
|
|
return ptr
|
|
}
|
|
|
|
// Get retrieves a pointer to a string, if present.
|
|
// Otherwise returns nil.
|
|
func (p *StringPool) Get(s string) *string {
|
|
p.RLock()
|
|
defer p.RUnlock()
|
|
|
|
// Get value
|
|
ptr, ok := p.values[s]
|
|
if !ok {
|
|
return nil
|
|
}
|
|
return ptr
|
|
}
|
|
|
|
// GarbageCollect releases all values, which have not been seen
|
|
// again.
|
|
func (p *StringPool) GarbageCollect() uint {
|
|
p.Lock()
|
|
defer p.Unlock()
|
|
var released uint = 0
|
|
for k, cnt := range p.counter {
|
|
if cnt < p.top {
|
|
delete(p.counter, k)
|
|
delete(p.values, k)
|
|
released++
|
|
}
|
|
}
|
|
p.top++ // Next generation
|
|
return released
|
|
}
|