@@ -8,13 +8,13 @@ import (
8
8
)
9
9
10
10
// TimePriorityQueue is a priority queue that dequeues elements at (or after) a specified time, and prioritizes elements based on a priority value. It is safe for concurrent use.
11
- type TimePriorityQueue [T any ] struct {
11
+ type TimePriorityQueue [T equals [ T ] ] struct {
12
12
mu sync.Mutex
13
13
tqueue TimeQueue [priorityEntry [T ]]
14
14
ready genericHeap [priorityEntry [T ]]
15
15
}
16
16
17
- func NewTimePriorityQueue [T any ]() * TimePriorityQueue [T ] {
17
+ func NewTimePriorityQueue [T equals [ T ] ]() * TimePriorityQueue [T ] {
18
18
return & TimePriorityQueue [T ]{
19
19
tqueue : TimeQueue [priorityEntry [T ]]{},
20
20
ready : genericHeap [priorityEntry [T ]]{},
@@ -23,33 +23,80 @@ func NewTimePriorityQueue[T any]() *TimePriorityQueue[T] {
23
23
24
24
func (t * TimePriorityQueue [T ]) Len () int {
25
25
t .mu .Lock ()
26
+ t .tqueue .mu .Lock ()
26
27
defer t .mu .Unlock ()
27
- return t .tqueue .Len () + t .ready .Len ()
28
+ defer t .tqueue .mu .Unlock ()
29
+ return t .tqueue .heap .Len () + t .ready .Len ()
28
30
}
29
31
30
32
func (t * TimePriorityQueue [T ]) Peek () T {
31
33
t .mu .Lock ()
34
+ t .tqueue .mu .Lock ()
32
35
defer t .mu .Unlock ()
36
+ defer t .tqueue .mu .Unlock ()
33
37
34
38
if t .ready .Len () > 0 {
35
39
return t .ready .Peek ().v
36
40
}
37
- return t .tqueue .Peek ().v
41
+ if t .tqueue .heap .Len () > 0 {
42
+ return t .tqueue .heap .Peek ().v .v
43
+ }
44
+ var zero T
45
+ return zero
38
46
}
39
47
40
48
func (t * TimePriorityQueue [T ]) Reset () []T {
41
49
t .mu .Lock ()
50
+ t .tqueue .mu .Lock ()
42
51
defer t .mu .Unlock ()
52
+ defer t .tqueue .mu .Unlock ()
53
+
43
54
var res []T
44
55
for t .ready .Len () > 0 {
45
56
res = append (res , heap .Pop (& t .ready ).(priorityEntry [T ]).v )
46
57
}
47
- for t .tqueue .Len () > 0 {
58
+ for t .tqueue .heap . Len () > 0 {
48
59
res = append (res , heap .Pop (& t .tqueue .heap ).(timeQueueEntry [priorityEntry [T ]]).v .v )
49
60
}
50
61
return res
51
62
}
52
63
64
+ func (t * TimePriorityQueue [T ]) GetAll () []T {
65
+ t .mu .Lock ()
66
+ t .tqueue .mu .Lock ()
67
+ defer t .mu .Unlock ()
68
+ defer t .tqueue .mu .Unlock ()
69
+ res := make ([]T , 0 , t .tqueue .heap .Len ()+ t .ready .Len ())
70
+ for _ , entry := range t .tqueue .heap {
71
+ res = append (res , entry .v .v )
72
+ }
73
+ for _ , entry := range t .ready {
74
+ res = append (res , entry .v )
75
+ }
76
+ return res
77
+ }
78
+
79
+ func (t * TimePriorityQueue [T ]) Remove (v T ) {
80
+ t .mu .Lock ()
81
+ t .tqueue .mu .Lock ()
82
+ defer t .mu .Unlock ()
83
+ defer t .tqueue .mu .Unlock ()
84
+
85
+ for idx := 0 ; idx < t .tqueue .heap .Len (); idx ++ {
86
+ if t .tqueue .heap [idx ].v .v .Eq (v ) {
87
+ heap .Remove (& t .tqueue .heap , idx )
88
+ return
89
+ }
90
+ }
91
+
92
+ for idx := 0 ; idx < t .ready .Len (); idx ++ {
93
+ if t .ready [idx ].v .Eq (v ) {
94
+ heap .Remove (& t .ready , idx )
95
+ return
96
+ }
97
+ }
98
+ }
99
+
53
100
func (t * TimePriorityQueue [T ]) Enqueue (at time.Time , priority int , v T ) {
54
101
t .mu .Lock ()
55
102
t .tqueue .Enqueue (at , priorityEntry [T ]{at , priority , v })
@@ -59,15 +106,17 @@ func (t *TimePriorityQueue[T]) Enqueue(at time.Time, priority int, v T) {
59
106
func (t * TimePriorityQueue [T ]) Dequeue (ctx context.Context ) T {
60
107
t .mu .Lock ()
61
108
for {
109
+ t .tqueue .mu .Lock ()
62
110
for t .tqueue .heap .Len () > 0 {
63
- thead := t .tqueue .Peek () // peek at the head of the time queue
111
+ thead := t .tqueue .heap . Peek () // peek at the head of the time queue
64
112
if thead .at .Before (time .Now ()) {
65
113
tqe := heap .Pop (& t .tqueue .heap ).(timeQueueEntry [priorityEntry [T ]])
66
114
heap .Push (& t .ready , tqe .v )
67
115
} else {
68
116
break
69
117
}
70
118
}
119
+ t .tqueue .mu .Unlock ()
71
120
if t .ready .Len () > 0 {
72
121
defer t .mu .Unlock ()
73
122
return heap .Pop (& t .ready ).(priorityEntry [T ]).v
@@ -80,7 +129,7 @@ func (t *TimePriorityQueue[T]) Dequeue(ctx context.Context) T {
80
129
}
81
130
}
82
131
83
- type priorityEntry [T any ] struct {
132
+ type priorityEntry [T equals [ T ] ] struct {
84
133
at time.Time
85
134
priority int
86
135
v T
@@ -89,3 +138,7 @@ type priorityEntry[T any] struct {
89
138
func (t priorityEntry [T ]) Less (other priorityEntry [T ]) bool {
90
139
return t .priority > other .priority
91
140
}
141
+
142
+ func (t priorityEntry [T ]) Eq (other priorityEntry [T ]) bool {
143
+ return t .at == other .at && t .priority == other .priority && t .v .Eq (other .v )
144
+ }
0 commit comments