Changed from a static channel queue to a dynamic queue for nodes
parent
3eee736f97
commit
11e7df2bde
@ -1,6 +1,71 @@
|
|||||||
package graphvent
|
package graphvent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
type Message struct {
|
type Message struct {
|
||||||
Node NodeID
|
Node NodeID
|
||||||
Signal Signal
|
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