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