go-pus/streams_map.go
DataHoarder c9b07c6bec
All checks were successful
continuous-integration/drone/push Build is passing
Added +build comment
2022-01-30 01:33:20 +01:00

66 lines
1.7 KiB
Go

// Copyright © Go Opus Authors (see AUTHORS file)
//
// License for use of this code is detailed in the LICENSE file
//go:build !nolibopusfile
// +build !nolibopusfile
package opus
import (
"sync"
"sync/atomic"
)
// A map of simple integers to the actual pointers to stream structs. Avoids
// passing pointers into the Go heap to C.
//
// As per the CGo pointers design doc for go 1.6:
//
// A particular unsafe area is C code that wants to hold on to Go func and
// pointer values for future callbacks from C to Go. This works today but is not
// permitted by the invariant. It is hard to detect. One safe approach is: Go
// code that wants to preserve funcs/pointers stores them into a map indexed by
// an int. Go code calls the C code, passing the int, which the C code may store
// freely. When the C code wants to call into Go, it passes the int to a Go
// function that looks in the map and makes the call. An explicit call is
// required to release the value from the map if it is no longer needed, but
// that was already true before.
//
// - https://github.com/golang/proposal/blob/master/design/12416-cgo-pointers.md
type streamsMap struct {
sync.RWMutex
m map[uintptr]*Stream
counter uintptr
}
func (sm *streamsMap) Get(id uintptr) *Stream {
sm.RLock()
defer sm.RUnlock()
return sm.m[id]
}
func (sm *streamsMap) Del(s *Stream) {
sm.Lock()
defer sm.Unlock()
delete(sm.m, s.id)
}
// NextId returns a unique ID for each call.
func (sm *streamsMap) NextId() uintptr {
return atomic.AddUintptr(&sm.counter, 1)
}
func (sm *streamsMap) Save(s *Stream) {
sm.Lock()
defer sm.Unlock()
sm.m[s.id] = s
}
func newStreamsMap() *streamsMap {
return &streamsMap{
counter: 0,
m: map[uintptr]*Stream{},
}
}