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  }