ident: system identifier generator
This is pretty fast and guarantees uniqueness when initialised correctly. Signed-off-by: Yonah <contrib@gensokyo.uk>
This commit is contained in:
@@ -6,7 +6,10 @@ import (
|
||||
"encoding"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand/v2"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
@@ -97,3 +100,47 @@ func (full *F[V, T]) UnmarshalText(data []byte) (err error) {
|
||||
}
|
||||
return full.Remote.UnmarshalText(data[sz+1:])
|
||||
}
|
||||
|
||||
// PartG is machine-specific state of [Generator].
|
||||
type PartG struct {
|
||||
// Deployment site, typically denoting a datacenter servicing a region.
|
||||
Site uint32
|
||||
// Servicing host behind load balancer, unique within its Site.
|
||||
Host uint32
|
||||
}
|
||||
|
||||
// A Generator emits unique instances of [S].
|
||||
type Generator struct {
|
||||
PartG
|
||||
mu sync.Mutex
|
||||
r rand.Source
|
||||
}
|
||||
|
||||
// S populates the value pointed to by p with a new unique value.
|
||||
func (g *Generator) S(p *S) {
|
||||
g.mu.Lock()
|
||||
*p = S{PartG: g.PartG, Time: uint64(time.Now().UnixNano()), ID: g.r.Uint64()}
|
||||
g.mu.Unlock()
|
||||
}
|
||||
|
||||
// NewS creates a unique instance of [S] and returns its address.
|
||||
func (g *Generator) NewS() *S {
|
||||
var sid S
|
||||
g.S(&sid)
|
||||
return &sid
|
||||
}
|
||||
|
||||
// M populates the value pointed to by p with a new unique value.
|
||||
func (g *Generator) M(p *PartM, serial uint64) {
|
||||
g.mu.Lock()
|
||||
*p = PartM{Serial: serial, Time: uint64(time.Now().UnixNano()), ID: g.r.Uint64()}
|
||||
g.mu.Unlock()
|
||||
}
|
||||
|
||||
// New initialises a new instance of [Generator] and returns its address.
|
||||
func New(site, host uint32) *Generator {
|
||||
return &Generator{PartG{site, host}, sync.Mutex{}, rand.NewPCG(
|
||||
uint64(site)<<32|uint64(host),
|
||||
uint64(time.Now().UnixNano()),
|
||||
)}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user