File tree Expand file tree Collapse file tree 4 files changed +37
-61
lines changed
Expand file tree Collapse file tree 4 files changed +37
-61
lines changed Original file line number Diff line number Diff line change 11package don
22
3- import (
4- "reflect"
5- "unsafe"
6- )
3+ import "reflect"
74
85func newNilCheck (zero any ) func (v any ) bool {
96 typ := reflect .TypeOf (zero )
@@ -19,22 +16,12 @@ func newNilCheck(zero any) func(v any) bool {
1916 return func (v any ) bool { return v == zero }
2017 case reflect .Map :
2118 // Return true for and nil map.
22- return func (v any ) bool {
23- return (* emptyInterface )(unsafe .Pointer (& v )).ptr == nil
24- }
19+ return func (v any ) bool { return dataOf (v ) == nil }
2520 case reflect .Slice :
2621 // Return true for nil slice.
27- return func (v any ) bool {
28- return (* reflect .SliceHeader )((* emptyInterface )(unsafe .Pointer (& v )).ptr ).Data == 0
29- }
22+ return func (v any ) bool { return (* reflect .SliceHeader )(dataOf (v )).Data == 0 }
3023 default :
3124 // Return false for all others.
3225 return func (v any ) bool { return false }
3326 }
3427}
35-
36- // emptyInterface is the header for an interface{} value.
37- type emptyInterface struct {
38- typ unsafe.Pointer
39- ptr unsafe.Pointer
40- }
Original file line number Diff line number Diff line change @@ -10,12 +10,6 @@ type pool[T any] interface {
1010 Put (* T )
1111}
1212
13- type resetter interface {
14- Reset ()
15- }
16-
17- var resetterType = reflect .TypeOf ((* resetter )(nil )).Elem ()
18-
1913type requestPool [T any ] struct {
2014 pool sync.Pool
2115 reset func (* T )
@@ -37,21 +31,17 @@ func newRequestPool[T any](zero T) pool[T] {
3731 * v = zero
3832 }
3933 } else {
34+ rtype := dataOf (typ )
4035 elem := typ .Elem ()
36+ elemrtype := dataOf (elem )
37+ zero := dataOf (reflect .New (elem ).Elem ().Interface ())
38+
4139 p .pool .New = func () any {
42- v := reflect . New ( elem ). Interface ( ).(T ) //nolint:forcetypeassert
40+ v := packEface ( rtype , unsafe_New ( elemrtype ) ).(T ) //nolint:forcetypeassert
4341 return & v
4442 }
45-
46- if typ .Implements (resetterType ) {
47- p .reset = func (v * T ) {
48- any (* v ).(resetter ).Reset () //nolint:forcetypeassert
49- }
50- } else {
51- zeroValue := reflect .New (elem ).Elem ()
52- p .reset = func (v * T ) {
53- reflect .ValueOf (v ).Elem ().Elem ().Set (zeroValue )
54- }
43+ p .reset = func (v * T ) {
44+ typedmemmove (elemrtype , dataOf (* v ), zero )
5545 }
5646 }
5747
Original file line number Diff line number Diff line change @@ -60,32 +60,4 @@ func TestRequestPool(t *testing.T) {
6060 }
6161 }
6262 })
63-
64- t .Run ("Resetter" , func (t * testing.T ) {
65- zero := & itemResetter {}
66- pool := don .NewRequestPool (zero )
67-
68- for i := 0 ; i < 100 ; i ++ {
69- p := pool .Get ()
70- v := * p
71- v .String = "test"
72- v .Pointer = & v .String
73- pool .Put (p )
74- }
75-
76- for i := 0 ; i < 100 ; i ++ {
77- if ! reflect .DeepEqual (& zero , pool .Get ()) {
78- t .Fatal ("should be zero value" )
79- }
80- }
81- })
82- }
83-
84- type itemResetter struct {
85- String string
86- Pointer * string
87- }
88-
89- func (ir * itemResetter ) Reset () {
90- * ir = itemResetter {}
9163}
Original file line number Diff line number Diff line change 1+ package don
2+
3+ import "unsafe"
4+
5+ //go:linkname unsafe_New reflect.unsafe_New
6+ func unsafe_New (unsafe.Pointer ) unsafe.Pointer //nolint:revive
7+
8+ //go:linkname typedmemmove reflect.typedmemmove
9+ func typedmemmove (t , dst , src unsafe.Pointer )
10+
11+ // emptyInterface is the header for an interface{} value.
12+ type emptyInterface struct {
13+ typ unsafe.Pointer
14+ ptr unsafe.Pointer
15+ }
16+
17+ func dataOf (v any ) unsafe.Pointer {
18+ return (* emptyInterface )(unsafe .Pointer (& v )).ptr
19+ }
20+
21+ func packEface (typ , ptr unsafe.Pointer ) any {
22+ var i any
23+ e := (* emptyInterface )(unsafe .Pointer (& i ))
24+ e .typ = typ
25+ e .ptr = ptr
26+ return i
27+ }
You can’t perform that action at this time.
0 commit comments