65 lines
1.7 KiB
Go
65 lines
1.7 KiB
Go
|
// Copyright © Go Opus Authors (see AUTHORS file)
|
||
|
//
|
||
|
// License for use of this code is detailed in the LICENSE file
|
||
|
|
||
|
// +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{},
|
||
|
}
|
||
|
}
|