-
Notifications
You must be signed in to change notification settings - Fork 39
Expand file tree
/
Copy pathidle_slice.go
More file actions
74 lines (64 loc) · 1.86 KB
/
Copy pathidle_slice.go
File metadata and controls
74 lines (64 loc) · 1.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package agilepool
import (
"sync/atomic"
"time"
)
// Slice implements IdleWorkerContainer using a dynamic array (slice).
// Workers are stored in FIFO order by insertion time, matching the behavior
// of LinkedList. Add appends to the tail, Pop removes from the head.
// Not safe for concurrent use; the caller (Pool) serializes access via muIdle.
type Slice struct {
workers []*worker
length int64
}
// Add appends a worker to the tail of the slice. O(1) amortized.
func (s *Slice) Add(w *worker) {
s.workers = append(s.workers, w)
atomic.AddInt64(&s.length, 1)
}
// Pop removes and returns the worker at the head of the slice (FIFO).
// Returns nil if the slice is empty. O(n) due to shifting elements.
func (s *Slice) Pop() *worker {
if s.Len() == 0 {
return nil
}
w := s.workers[0]
s.workers[0] = nil
s.workers = s.workers[1:]
atomic.AddInt64(&s.length, -1)
return w
}
// RemoveExpired removes all workers whose lastActiveAt + expiry <= now.
// Workers are ordered by insertion time, which does not guarantee monotonic
// lastActiveAt values, so all workers must be scanned. Survivors retain FIFO
// order. O(n) where n is the number of idle workers.
func (s *Slice) RemoveExpired(now time.Time, expiry time.Duration) int {
if s.Len() == 0 {
return 0
}
cutoff := now.Add(-expiry)
originalLen := len(s.workers)
survivors := s.workers[:0]
for _, w := range s.workers {
if w.lastActiveAt.After(cutoff) {
survivors = append(survivors, w)
}
}
removed := originalLen - len(survivors)
if removed > 0 {
clear(s.workers[len(survivors):])
s.workers = survivors
atomic.AddInt64(&s.length, -int64(removed))
}
return removed
}
// Len returns the number of workers in the slice.
func (s *Slice) Len() int64 {
return atomic.LoadInt64(&s.length)
}
// newSlice creates a new empty Slice.
func newSlice() *Slice {
return &Slice{
workers: make([]*worker, 0),
}
}