Changed from a static channel queue to a dynamic queue for nodes
parent
3eee736f97
commit
11e7df2bde
@ -1,6 +1,71 @@
|
||||
package graphvent
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Message struct {
|
||||
Node NodeID
|
||||
Signal Signal
|
||||
}
|
||||
|
||||
type MessageQueue struct {
|
||||
out chan Message
|
||||
in chan Message
|
||||
buffer []Message
|
||||
write_cursor int
|
||||
read_cursor int
|
||||
}
|
||||
|
||||
func (queue *MessageQueue) ProcessIncoming(message Message) {
|
||||
if (queue.write_cursor + 1) == queue.read_cursor || ((queue.write_cursor + 1) == len(queue.buffer) && queue.read_cursor == 0) {
|
||||
fmt.Printf("Growing queue from %d to %d\n", len(queue.buffer), len(queue.buffer)*2)
|
||||
|
||||
new_buffer := make([]Message, len(queue.buffer) * 2)
|
||||
|
||||
copy(new_buffer, queue.buffer[queue.read_cursor:])
|
||||
first_chunk := len(queue.buffer) - queue.read_cursor
|
||||
copy(new_buffer[first_chunk:], queue.buffer[0:queue.write_cursor])
|
||||
|
||||
queue.write_cursor = len(queue.buffer) - 1
|
||||
queue.read_cursor = 0
|
||||
queue.buffer = new_buffer
|
||||
}
|
||||
|
||||
queue.buffer[queue.write_cursor] = message
|
||||
queue.write_cursor += 1
|
||||
if queue.write_cursor >= len(queue.buffer) {
|
||||
queue.write_cursor = 0
|
||||
}
|
||||
}
|
||||
|
||||
func NewMessageQueue(initial int) (chan<- Message, <-chan Message) {
|
||||
queue := MessageQueue{
|
||||
out: make(chan Message, 0),
|
||||
in: make(chan Message, 0),
|
||||
buffer: make([]Message, initial),
|
||||
write_cursor: 0,
|
||||
read_cursor: 0,
|
||||
}
|
||||
|
||||
go func(queue *MessageQueue) {
|
||||
for true {
|
||||
if queue.write_cursor != queue.read_cursor {
|
||||
select {
|
||||
case incoming := <-queue.in:
|
||||
queue.ProcessIncoming(incoming)
|
||||
case queue.out <- queue.buffer[queue.read_cursor]:
|
||||
queue.read_cursor += 1
|
||||
if queue.read_cursor >= len(queue.buffer) {
|
||||
queue.read_cursor = 0
|
||||
}
|
||||
}
|
||||
} else {
|
||||
message := <-queue.in
|
||||
queue.ProcessIncoming(message)
|
||||
}
|
||||
}
|
||||
}(&queue)
|
||||
|
||||
return queue.in, queue.out
|
||||
}
|
||||
|
@ -0,0 +1,35 @@
|
||||
package graphvent
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func sendBatch(start, end uint64, in chan<- Message) {
|
||||
for i := start; i <= end; i++ {
|
||||
var id NodeID
|
||||
binary.BigEndian.PutUint64(id[:], i)
|
||||
in <- Message{id, nil}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMessageQueue(t *testing.T) {
|
||||
in, out := NewMessageQueue(10)
|
||||
|
||||
for i := uint64(0); i < 1000; i++ {
|
||||
go sendBatch(1000*i, (1000*(i+1))-1, in)
|
||||
}
|
||||
|
||||
seen := map[NodeID]any{}
|
||||
for i := uint64(0); i < 1000*1000; i++ {
|
||||
read := <-out
|
||||
_, already_seen := seen[read.Node]
|
||||
if already_seen {
|
||||
t.Fatalf("Signal %d had duplicate NodeID %s", i, read.Node)
|
||||
} else {
|
||||
seen[read.Node] = nil
|
||||
}
|
||||
}
|
||||
|
||||
t.Logf("Processed 1M signals through queue")
|
||||
}
|
Loading…
Reference in New Issue