@@ -4,91 +4,112 @@ import (
44 "encoding/binary"
55 "io"
66 "sync/atomic"
7+ "unsafe"
78
89 "github.com/rsocket/rsocket-go/core"
910 "github.com/rsocket/rsocket-go/internal/common"
1011 "github.com/rsocket/rsocket-go/internal/u24"
12+ uberatomic "go.uber.org/atomic"
1113)
1214
1315// bufferedFrame is basic frame implementation.
1416type bufferedFrame struct {
15- inner * common. ByteBuff
16- refs int32
17+ innerPtr unsafe. Pointer
18+ refs uberatomic. Int32
1719}
1820
1921func 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
2426}
2527
2628func (f * bufferedFrame ) IncRef () int32 {
27- return atomic . AddInt32 ( & f .refs , 1 )
29+ return f .refs . Add ( 1 )
2830}
2931
3032func (f * bufferedFrame ) RefCnt () int32 {
31- return atomic . LoadInt32 ( & f .refs )
33+ return f .refs . Load ( )
3234}
3335
3436func (f * bufferedFrame ) Header () core.FrameHeader {
35- if f .inner == nil {
37+ inner := (* common .ByteBuff )(atomic .LoadPointer (& f .innerPtr ))
38+ if inner == nil {
3639 panic ("frame has been released!" )
3740 }
38- b := f . inner .Bytes ()
41+ b := inner .Bytes ()
3942 _ = b [core .FrameHeaderLen - 1 ]
4043 var h core.FrameHeader
4144 copy (h [:], b )
4245 return h
4346}
4447
4548func (f * bufferedFrame ) HasFlag (flag core.FrameFlag ) bool {
46- if f .inner == nil {
49+ inner := (* common .ByteBuff )(atomic .LoadPointer (& f .innerPtr ))
50+ if inner == nil {
4751 panic ("frame has been released!" )
4852 }
49- n := binary .BigEndian .Uint16 (f . inner .Bytes ()[4 :6 ])
53+ n := binary .BigEndian .Uint16 (inner .Bytes ()[4 :6 ])
5054 return core .FrameFlag (n & 0x03FF )& flag == flag
5155}
5256
5357func (f * bufferedFrame ) StreamID () uint32 {
54- if f .inner == nil {
58+ inner := (* common .ByteBuff )(atomic .LoadPointer (& f .innerPtr ))
59+ if inner == nil {
5560 panic ("frame has been released!" )
5661 }
57- return binary .BigEndian .Uint32 (f . inner .Bytes ()[:4 ])
62+ return binary .BigEndian .Uint32 (inner .Bytes ()[:4 ])
5863}
5964
6065// Release releases resource.
6166func (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+ }
6580 }
6681}
6782
6883// Body returns frame body.
6984func (f * bufferedFrame ) Body () []byte {
70- if f .inner == nil {
85+ inner := (* common .ByteBuff )(atomic .LoadPointer (& f .innerPtr ))
86+ if inner == nil {
7187 return nil
7288 }
73- b := f . inner .Bytes ()
89+ b := inner .Bytes ()
7490 _ = b [core .FrameHeaderLen - 1 ]
7591 return b [core .FrameHeaderLen :]
7692}
7793
7894// Len returns length of frame.
7995func (f * bufferedFrame ) Len () int {
80- if f .inner == nil {
96+ inner := (* common .ByteBuff )(atomic .LoadPointer (& f .innerPtr ))
97+ if inner == nil {
8198 return 0
8299 }
83- return f . inner .Len ()
100+ return inner .Len ()
84101}
85102
86103// WriteTo write frame to writer.
87104func (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 {
89110 return
90111 }
91- n , err = f . inner .WriteTo (w )
112+ n , err = inner .WriteTo (w )
92113 return
93114}
94115
0 commit comments