@@ -4,91 +4,112 @@ import (
4
4
"encoding/binary"
5
5
"io"
6
6
"sync/atomic"
7
+ "unsafe"
7
8
8
9
"github.com/rsocket/rsocket-go/core"
9
10
"github.com/rsocket/rsocket-go/internal/common"
10
11
"github.com/rsocket/rsocket-go/internal/u24"
12
+ uberatomic "go.uber.org/atomic"
11
13
)
12
14
13
15
// bufferedFrame is basic frame implementation.
14
16
type bufferedFrame struct {
15
- inner * common. ByteBuff
16
- refs int32
17
+ innerPtr unsafe. Pointer
18
+ refs uberatomic. Int32
17
19
}
18
20
19
21
func newBufferedFrame (inner * common.ByteBuff ) * bufferedFrame {
20
- return & bufferedFrame {
21
- inner : inner ,
22
- refs : 1 ,
23
- }
22
+ frame := & bufferedFrame {}
23
+ atomic . StorePointer ( & frame . innerPtr , unsafe . Pointer ( inner ))
24
+ frame . refs . Store ( 1 )
25
+ return frame
24
26
}
25
27
26
28
func (f * bufferedFrame ) IncRef () int32 {
27
- return atomic . AddInt32 ( & f .refs , 1 )
29
+ return f .refs . Add ( 1 )
28
30
}
29
31
30
32
func (f * bufferedFrame ) RefCnt () int32 {
31
- return atomic . LoadInt32 ( & f .refs )
33
+ return f .refs . Load ( )
32
34
}
33
35
34
36
func (f * bufferedFrame ) Header () core.FrameHeader {
35
- if f .inner == nil {
37
+ inner := (* common .ByteBuff )(atomic .LoadPointer (& f .innerPtr ))
38
+ if inner == nil {
36
39
panic ("frame has been released!" )
37
40
}
38
- b := f . inner .Bytes ()
41
+ b := inner .Bytes ()
39
42
_ = b [core .FrameHeaderLen - 1 ]
40
43
var h core.FrameHeader
41
44
copy (h [:], b )
42
45
return h
43
46
}
44
47
45
48
func (f * bufferedFrame ) HasFlag (flag core.FrameFlag ) bool {
46
- if f .inner == nil {
49
+ inner := (* common .ByteBuff )(atomic .LoadPointer (& f .innerPtr ))
50
+ if inner == nil {
47
51
panic ("frame has been released!" )
48
52
}
49
- n := binary .BigEndian .Uint16 (f . inner .Bytes ()[4 :6 ])
53
+ n := binary .BigEndian .Uint16 (inner .Bytes ()[4 :6 ])
50
54
return core .FrameFlag (n & 0x03FF )& flag == flag
51
55
}
52
56
53
57
func (f * bufferedFrame ) StreamID () uint32 {
54
- if f .inner == nil {
58
+ inner := (* common .ByteBuff )(atomic .LoadPointer (& f .innerPtr ))
59
+ if inner == nil {
55
60
panic ("frame has been released!" )
56
61
}
57
- return binary .BigEndian .Uint32 (f . inner .Bytes ()[:4 ])
62
+ return binary .BigEndian .Uint32 (inner .Bytes ()[:4 ])
58
63
}
59
64
60
65
// Release releases resource.
61
66
func (f * bufferedFrame ) Release () {
62
- if f != nil && f .inner != nil && atomic .AddInt32 (& f .refs , - 1 ) == 0 {
63
- common .ReturnByteBuff (f .inner )
64
- f .inner = nil
67
+ if f == nil {
68
+ return
69
+ }
70
+ refs := f .refs .Add (- 1 )
71
+ if refs > 0 {
72
+ return
73
+ }
74
+ inner := (* common .ByteBuff )(atomic .LoadPointer (& f .innerPtr ))
75
+ if inner != nil {
76
+ swapped := atomic .CompareAndSwapPointer (& f .innerPtr , unsafe .Pointer (inner ), unsafe .Pointer (nil ))
77
+ if swapped {
78
+ common .ReturnByteBuff (inner )
79
+ }
65
80
}
66
81
}
67
82
68
83
// Body returns frame body.
69
84
func (f * bufferedFrame ) Body () []byte {
70
- if f .inner == nil {
85
+ inner := (* common .ByteBuff )(atomic .LoadPointer (& f .innerPtr ))
86
+ if inner == nil {
71
87
return nil
72
88
}
73
- b := f . inner .Bytes ()
89
+ b := inner .Bytes ()
74
90
_ = b [core .FrameHeaderLen - 1 ]
75
91
return b [core .FrameHeaderLen :]
76
92
}
77
93
78
94
// Len returns length of frame.
79
95
func (f * bufferedFrame ) Len () int {
80
- if f .inner == nil {
96
+ inner := (* common .ByteBuff )(atomic .LoadPointer (& f .innerPtr ))
97
+ if inner == nil {
81
98
return 0
82
99
}
83
- return f . inner .Len ()
100
+ return inner .Len ()
84
101
}
85
102
86
103
// WriteTo write frame to writer.
87
104
func (f * bufferedFrame ) WriteTo (w io.Writer ) (n int64 , err error ) {
88
- if f == nil || f .inner == nil {
105
+ if f == nil {
106
+ return
107
+ }
108
+ inner := (* common .ByteBuff )(atomic .LoadPointer (& f .innerPtr ))
109
+ if inner == nil {
89
110
return
90
111
}
91
- n , err = f . inner .WriteTo (w )
112
+ n , err = inner .WriteTo (w )
92
113
return
93
114
}
94
115
0 commit comments