@@ -2,7 +2,6 @@ package orbyte
22
33import (
44 "runtime"
5- "strconv"
65 "sync/atomic"
76)
87
@@ -16,96 +15,59 @@ type Item[T any] struct {
1615 cfg any
1716
1817 stat status
19- ref * Item [T ]
20- refc int32 // refc -1 means transferred / destroyed
2118
2219 val T
2320}
2421
25- func (b * Item [T ]) incref () {
26- atomic .AddInt32 (& b .refc , 1 )
27- }
28-
29- func (b * Item [T ]) decref () {
30- atomic .AddInt32 (& b .refc , - 1 )
31- }
32-
33- // Trans ownership to a new item and
34- // destroy original item immediately.
35- //
36- // The value in new item will not be Reset().
22+ // Trans disable inner val being reset by
23+ // destroy and return a safe copy of val.
3724//
38- // Call this function to drop your ownership
39- // before passing it to another function
40- // that is not controlled by you .
25+ // This method is not thread-safe.
26+ // Only call once on one item.
27+ // The item will be destroyed after calling Trans() .
4128//
42- // Avoid to call this function after calling Ref().
43- func (b * Item [T ]) Trans () (tb * Item [T ]) {
29+ // Use it to drop your ownership
30+ // before passing val (not its pointer)
31+ // to another function that is not controlled by you.
32+ func (b * Item [T ]) Trans () T {
4433 if b .stat .hasdestroyed () {
4534 panic ("use after destroy" )
4635 }
47- if b .ref != nil {
48- panic ("cannot trans ref" )
49- }
50- tb = b .pool .newempty ()
51- * tb = * b
52- tb .stat = status (atomic .SwapUintptr (
36+ val := b .val
37+ atomic .StoreUintptr (
5338 (* uintptr )(& b .stat ), uintptr (destroyedstatus ),
54- ))
55- tb .refc = 0
56- tb .stat .setintrans (true )
57- b .destroybystat (status (0 ))
58- return tb
39+ )
40+ runtime .KeepAlive (b )
41+ b .destroybystat (0 )
42+ return val
5943}
6044
61- // HasInvolved whether this item is buffered.
45+ // HasInvolved whether this item is buffered
46+ // and will be Reset on putting back.
6247func (b * Item [T ]) HasInvolved () bool {
6348 return b .stat .isbuffered ()
6449}
6550
66- // IsTrans whether this item has been marked as trans.
67- func (b * Item [T ]) IsTrans () bool {
68- return b .stat .isintrans ()
69- }
70-
71- // IsRef whether this item is a reference.
72- func (b * Item [T ]) IsRef () bool {
73- return b .ref != nil
74- }
75-
76- // Unwrap use value of the item
77- func (b * Item [T ]) Unwrap () T {
78- if b .stat .hasdestroyed () {
79- panic ("use after destroy" )
80- }
81- return b .val
82- }
83-
84- // Pointer use pointer value of the item
85- func (b * Item [T ]) Pointer () * T {
51+ // V use value of the item.
52+ //
53+ // This operation is safe in function f.
54+ func (b * Item [T ]) V (f func (T )) {
8655 if b .stat .hasdestroyed () {
8756 panic ("use after destroy" )
8857 }
89- return & b .val
58+ f (b .val )
59+ runtime .KeepAlive (b )
9060}
9161
92- // Ref gens new item without ownership .
62+ // P use pointer value of the item .
9363//
94- // It's a safe reference, thus calling this
95- // will not destroy the original item
96- // comparing with Trans().
97- func (b * Item [T ]) Ref () (rb * Item [T ]) {
64+ // This operation is safe in function f.
65+ func (b * Item [T ]) P (f func (* T )) {
9866 if b .stat .hasdestroyed () {
9967 panic ("use after destroy" )
10068 }
101- rb = b .pool .newempty ()
102- * rb = * b
103- rb .ref = b
104- rb .refc = 0
105- b .incref ()
106- rb .stat .setbuffered (false )
107- rb .stat .setintrans (false )
108- return
69+ f (& b .val )
70+ runtime .KeepAlive (b )
10971}
11072
11173// Copy data completely with separated ownership.
@@ -119,21 +81,9 @@ func (b *Item[T]) Copy() (cb *Item[T]) {
11981}
12082
12183func (b * Item [T ]) destroybystat (stat status ) {
122- if ! atomic .CompareAndSwapInt32 (& b .refc , 0 , - 1 ) {
123- if b .refc < 0 {
124- panic ("use imm. after destroy" )
125- }
126- panic ("cannot destroy: " + strconv .Itoa (int (b .refc )) + " refs remained" )
127- }
128- if b .ref != nil {
129- defer b .ref .decref ()
130- }
13184 switch {
13285 case stat .hasdestroyed ():
133- panic ("use after put back to pool" )
134- case stat .isintrans ():
135- var v T
136- b .val = v
86+ panic ("destroy after destroy" )
13787 case stat .isbuffered ():
13888 b .pool .pooler .Reset (& b .val )
13989 default :
@@ -158,10 +108,10 @@ func (b *Item[T]) ManualDestroy() {
158108// Only can call once.
159109func (b * Item [T ]) setautodestroy () * Item [T ] {
160110 runtime .SetFinalizer (b , func (item * Item [T ]) {
161- // no one is using, no concurrency issue.
162111 if item .stat .hasdestroyed () {
163112 panic ("unexpected hasdestroyed" )
164113 }
114+ // no one is using, no concurrency issue.
165115 item .destroybystat (item .stat )
166116 })
167117 return b
0 commit comments