github.com/GuanceCloud/cliutils@v1.1.21/pipeline/ptinput/ptwindow/pt_window.go (about) 1 // Package ptwindow impl pt context window 2 package ptwindow 3 4 import ( 5 "fmt" 6 "sync" 7 8 "github.com/GuanceCloud/cliutils/point" 9 ) 10 11 func PutbackPoints(pts ...*point.Point) { 12 if ptPool := point.GetPointPool(); ptPool != nil { 13 for _, pt := range pts { 14 if pt.HasFlag(point.Ppooled) { 15 ptPool.Put(pt) 16 } 17 } 18 } 19 } 20 21 type PtRing struct { 22 ring []*point.Point 23 pos int 24 25 notNil int 26 27 elemLimit int 28 } 29 30 func (w *PtRing) put(pt *point.Point) { 31 if w.pos >= len(w.ring) { 32 w.pos = 0 33 } 34 if w.ring[w.pos] != nil { 35 PutbackPoints(pt) 36 } 37 38 w.ring[w.pos] = pt 39 if pt != nil { 40 w.notNil++ 41 } 42 w.pos++ 43 } 44 45 func (w *PtRing) clean() []*point.Point { 46 if w.notNil == 0 { 47 return nil 48 } 49 50 w.notNil = 0 51 var r []*point.Point 52 53 for i := 0; i < len(w.ring); i++ { 54 if w.ring[i] != nil { 55 r = append(r, w.ring[i]) 56 w.ring[i] = nil 57 } 58 } 59 return r 60 } 61 62 func NewRing(elem int) (*PtRing, error) { 63 if elem <= 0 { 64 return nil, fmt.Errorf("invalid ring size: %d", elem) 65 } 66 67 return &PtRing{ 68 ring: make([]*point.Point, elem), 69 elemLimit: elem, 70 }, nil 71 } 72 73 type PtWindow struct { 74 ringBefore *PtRing 75 76 hit int // default 0 77 78 before int 79 after int 80 81 disableInsert bool 82 sync.Mutex 83 } 84 85 func (w *PtWindow) deprecated() { 86 w.Lock() 87 defer w.Unlock() 88 w.disableInsert = true 89 90 pts := w.ringBefore.clean() 91 PutbackPoints(pts...) 92 } 93 94 func (w *PtWindow) Move(pt *point.Point) []*point.Point { 95 w.Lock() 96 defer w.Unlock() 97 98 if w.hit > 0 { 99 w.hit-- 100 var rst []*point.Point 101 if w.ringBefore != nil { 102 if v := w.ringBefore.clean(); len(v) > 0 { 103 rst = append(rst, v...) 104 } 105 } 106 if pt != nil { 107 rst = append(rst, pt) 108 } 109 return rst 110 } else if w.ringBefore != nil && !w.disableInsert { 111 w.ringBefore.put(pt) 112 } 113 114 return nil 115 } 116 117 func (w *PtWindow) Hit() { 118 w.Lock() 119 w.hit = w.after 120 w.Unlock() 121 } 122 123 func NewWindow(before int, after int) *PtWindow { 124 w := &PtWindow{ 125 ringBefore: nil, 126 before: before, 127 after: after, 128 } 129 130 if before > 0 { 131 w.ringBefore, _ = NewRing(before) 132 } 133 134 return w 135 }