package http2
import (
)
type streamMetadata struct {
location *writeQueue
priority PriorityParam
}
type priorityWriteSchedulerRFC9218 struct {
control writeQueue
heads [8][2]*writeQueue
streams map[uint32]streamMetadata
queuePool writeQueuePool
prioritizeIncremental bool
priorityUpdateBuf struct {
streamID uint32
priority PriorityParam
}
}
func () WriteScheduler {
:= &priorityWriteSchedulerRFC9218{
streams: make(map[uint32]streamMetadata),
}
return
}
func ( *priorityWriteSchedulerRFC9218) ( uint32, OpenStreamOptions) {
if .streams[].location != nil {
panic(fmt.Errorf("stream %d already opened", ))
}
if == .priorityUpdateBuf.streamID {
.priorityUpdateBuf.streamID = 0
.priority = .priorityUpdateBuf.priority
}
:= .queuePool.get()
.streams[] = streamMetadata{
location: ,
priority: .priority,
}
, := .priority.urgency, .priority.incremental
if .heads[][] == nil {
.heads[][] =
.next =
.prev =
} else {
.prev = .heads[][].prev
.next = .heads[][]
.prev.next =
.next.prev =
}
}
func ( *priorityWriteSchedulerRFC9218) ( uint32) {
:= .streams[]
, , := .location, .priority.urgency, .priority.incremental
if == nil {
return
}
if .next == {
.heads[][] = nil
} else {
.prev.next = .next
.next.prev = .prev
if .heads[][] == {
.heads[][] = .next
}
}
delete(.streams, )
.queuePool.put()
}
func ( *priorityWriteSchedulerRFC9218) ( uint32, PriorityParam) {
:= .streams[]
, , := .location, .priority.urgency, .priority.incremental
if == nil {
.priorityUpdateBuf.streamID =
.priorityUpdateBuf.priority =
return
}
if .next == {
.heads[][] = nil
} else {
.prev.next = .next
.next.prev = .prev
if .heads[][] == {
.heads[][] = .next
}
}
, = .urgency, .incremental
if .heads[][] == nil {
.heads[][] =
.next =
.prev =
} else {
.prev = .heads[][].prev
.next = .heads[][]
.prev.next =
.next.prev =
}
.streams[] = streamMetadata{
location: ,
priority: ,
}
}
func ( *priorityWriteSchedulerRFC9218) ( FrameWriteRequest) {
if .isControl() {
.control.push()
return
}
:= .streams[.StreamID()].location
if == nil {
if .DataSize() > 0 {
panic("add DATA on non-open stream")
}
.control.push()
return
}
.push()
}
func ( *priorityWriteSchedulerRFC9218) () (FrameWriteRequest, bool) {
if !.control.empty() {
return .control.shift(), true
}
.prioritizeIncremental = !.prioritizeIncremental
for := range .heads {
for := range .heads[] {
if .prioritizeIncremental {
= ( + 1) % 2
}
:= .heads[][]
if == nil {
continue
}
for {
if , := .consume(math.MaxInt32); {
if == 1 {
.heads[][] = .next
} else {
.heads[][] =
}
return , true
}
= .next
if == .heads[][] {
break
}
}
}
}
return FrameWriteRequest{}, false
}