entry.go raw

   1  package ring
   2  
   3  import (
   4  	"context"
   5  	"github.com/p9c/p9/pkg/log"
   6  	
   7  	"github.com/marusama/semaphore"
   8  )
   9  
  10  type Entry struct {
  11  	Sem     semaphore.Semaphore
  12  	Buf     []*log.Entry
  13  	Cursor  int
  14  	Full    bool
  15  	Clicked int
  16  	// Buttons []gel.Button
  17  	// Hiders  []gel.Button
  18  }
  19  
  20  // NewEntry creates a new entry ring buffer
  21  func NewEntry(size int) *Entry {
  22  	return &Entry{
  23  		Sem:     semaphore.New(1),
  24  		Buf:     make([]*log.Entry, size),
  25  		Cursor:  0,
  26  		Clicked: -1,
  27  		// Buttons: make([]gel.Button, size),
  28  		// Hiders:  make([]gel.Button, size),
  29  	}
  30  }
  31  
  32  // Clear sets the buffer back to initial state
  33  func (b *Entry) Clear() {
  34  	var e error
  35  	if e = b.Sem.Acquire(context.Background(), 1); !E.Chk(e) {
  36  		defer b.Sem.Release(1)
  37  		b.Cursor = 0
  38  		b.Clicked = -1
  39  		b.Full = false
  40  	}
  41  }
  42  
  43  // Len returns the length of the buffer
  44  func (b *Entry) Len() (out int) {
  45  	var e error
  46  	if e = b.Sem.Acquire(context.Background(), 1); !E.Chk(e) {
  47  		defer b.Sem.Release(1)
  48  		if b.Full {
  49  			out = len(b.Buf)
  50  		} else {
  51  			out = b.Cursor
  52  		}
  53  	}
  54  	return
  55  }
  56  
  57  // Get returns the value at the given index or nil if nothing
  58  func (b *Entry) Get(i int) (out *log.Entry) {
  59  	var e error
  60  	if e = b.Sem.Acquire(context.Background(), 1); !E.Chk(e) {
  61  		defer b.Sem.Release(1)
  62  		bl := len(b.Buf)
  63  		cursor := i
  64  		if i < bl {
  65  			if b.Full {
  66  				cursor = i + b.Cursor
  67  				if cursor >= bl {
  68  					cursor -= bl
  69  				}
  70  			}
  71  			// D.Ln("get entry", i, "len", bl, "cursor", b.Cursor, "position",
  72  			//	cursor)
  73  			out = b.Buf[cursor]
  74  		}
  75  	}
  76  	return
  77  }
  78  
  79  //
  80  // // GetButton returns the gel.Button of the entry
  81  // func (b *Entry) GetButton(i int) (out *gel.Button) {
  82  // 	if e = b.Sem.Acquire(context.Background(), 1); !E.Chk(e) {
  83  // 		defer b.Sem.Release(1)
  84  // 		bl := len(b.Buf)
  85  // 		cursor := i
  86  // 		if i < bl {
  87  // 			if b.Full {
  88  // 				cursor = i + b.Cursor
  89  // 				if cursor >= bl {
  90  // 					cursor -= bl
  91  // 				}
  92  // 			}
  93  // 			// D.Ln("get entry", i, "len", bl, "cursor", b.Cursor, "position",
  94  // 			//	cursor)
  95  // 			out = &b.Buttons[cursor]
  96  // 		}
  97  // 	}
  98  // 	return
  99  // }
 100  //
 101  // // GetHider returns the gel.Button of the entry
 102  // func (b *Entry) GetHider(i int) (out *gel.Button) {
 103  // 	if e = b.Sem.Acquire(context.Background(), 1); !E.Chk(e) {
 104  // 		defer b.Sem.Release(1)
 105  // 		bl := len(b.Buf)
 106  // 		cursor := i
 107  // 		if i < bl {
 108  // 			if b.Full {
 109  // 				cursor = i + b.Cursor
 110  // 				if cursor >= bl {
 111  // 					cursor -= bl
 112  // 				}
 113  // 			}
 114  // 			// D.Ln("get entry", i, "len", bl, "cursor", b.Cursor, "position",
 115  // 			//	cursor)
 116  // 			out = &b.Hiders[cursor]
 117  // 		}
 118  // 	}
 119  // 	return
 120  // }
 121  
 122  func (b *Entry) Add(value *log.Entry) {
 123  	var e error
 124  	if e = b.Sem.Acquire(context.Background(), 1); !E.Chk(e) {
 125  		defer b.Sem.Release(1)
 126  		if b.Cursor == len(b.Buf) {
 127  			b.Cursor = 0
 128  			if !b.Full {
 129  				b.Full = true
 130  			}
 131  		}
 132  		b.Buf[b.Cursor] = value
 133  		b.Cursor++
 134  	}
 135  }
 136  
 137  func (b *Entry) ForEach(fn func(v *log.Entry) error) (e error) {
 138  	if e = b.Sem.Acquire(context.Background(), 1); !E.Chk(e) {
 139  		c := b.Cursor
 140  		i := c + 1
 141  		if i == len(b.Buf) {
 142  			// D.Ln("hit the end")
 143  			i = 0
 144  		}
 145  		if !b.Full {
 146  			// D.Ln("buffer not yet full")
 147  			i = 0
 148  		}
 149  		// D.Ln(b.Buf)
 150  		for ; ; i++ {
 151  			if i == len(b.Buf) {
 152  				// D.Ln("passed the end")
 153  				i = 0
 154  			}
 155  			if i == c {
 156  				// D.Ln("reached cursor again")
 157  				break
 158  			}
 159  			// D.Ln(i, b.Cursor)
 160  			if e = fn(b.Buf[i]); E.Chk(e) {
 161  				break
 162  			}
 163  		}
 164  		b.Sem.Release(1)
 165  	}
 166  	return
 167  }
 168