github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/common/refs.go (about) 1 // Copyright 2021 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package common 16 17 import ( 18 "sync/atomic" 19 ) 20 21 type PinnedItem[T IRef] struct { 22 Val T 23 } 24 25 func (item *PinnedItem[T]) Close() { 26 item.Val.Unref() 27 } 28 29 func (item *PinnedItem[T]) Item() T { return item.Val } 30 31 // IRef is the general representation of the resources 32 // that should be managed with a reference count. 33 // Once the reference count reached 0, the OnZeroCB 34 // would be called. 35 type IRef interface { 36 RefCount() int64 37 // RefIfHasRef increment refcnt if existing cnt > 0 and return true, 38 // return false if cnt is zero. Note: the udpate is atomic 39 RefIfHasRef() bool 40 Ref() 41 Unref() 42 } 43 44 type OnZeroCB func() 45 46 type RefHelper struct { 47 Refs atomic.Int64 48 OnZeroCB OnZeroCB 49 } 50 51 func (helper *RefHelper) RefCount() int64 { 52 return helper.Refs.Load() 53 } 54 55 func (helper *RefHelper) Ref() { 56 helper.Refs.Add(1) 57 } 58 59 func (helper *RefHelper) RefIfHasRef() bool { 60 for val := helper.Refs.Load(); val > 0; val = helper.Refs.Load() { 61 if helper.Refs.CompareAndSwap(val, val+1) { 62 return true 63 } 64 } 65 return false 66 } 67 68 func (helper *RefHelper) Unref() { 69 v := helper.Refs.Add(-1) 70 if v == 0 { 71 if helper.OnZeroCB != nil { 72 helper.OnZeroCB() 73 } 74 } else if v < 0 { 75 panic("logic error") 76 } 77 }