forked from hraban/opus
-
Notifications
You must be signed in to change notification settings - Fork 0
/
streams_map.go
64 lines (55 loc) · 1.68 KB
/
streams_map.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// 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{},
}
}