writesched.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. // Copyright 2014 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // See https://code.google.com/p/go/source/browse/CONTRIBUTORS
  5. // Licensed under the same terms as Go itself:
  6. // https://code.google.com/p/go/source/browse/LICENSE
  7. package http2
  8. // frameWriteMsg is a request to write a frame.
  9. type frameWriteMsg struct {
  10. // write is the function that does the writing, once the
  11. // writeScheduler (below) has decided to select this frame
  12. // to write. The write functions are all defined in write.go.
  13. write func(ctx writeContext, v interface{}) error
  14. // v is the argument passed to the write function. See each
  15. // function in write.go to see which type they should be,
  16. // depending on what write is.
  17. v interface{}
  18. cost uint32 // if DATA, number of flow control bytes required
  19. stream *stream // used for prioritization
  20. endStream bool // stream is being closed locally
  21. // done, if non-nil, must be a buffered channel with space for
  22. // 1 message and is sent the return value from write (or an
  23. // earlier error) when the frame has been written.
  24. done chan error
  25. }
  26. // writeScheduler tracks pending frames to write, priorities, and decides
  27. // the next one to use. It is not thread-safe.
  28. type writeScheduler struct {
  29. slice []frameWriteMsg
  30. }
  31. func (ws *writeScheduler) empty() bool { return len(ws.slice) == 0 }
  32. func (ws *writeScheduler) add(wm frameWriteMsg) {
  33. ws.slice = append(ws.slice, wm)
  34. }
  35. // take returns
  36. func (ws *writeScheduler) take() frameWriteMsg {
  37. if ws.empty() {
  38. panic("internal error: writeScheduler.take called when empty")
  39. }
  40. // TODO:
  41. // -- prioritize all non-DATA frames first. they're not flow controlled anyway and
  42. // they're generally more important.
  43. // -- for all DATA frames that are enqueued (and we should enqueue []byte instead of FRAMES),
  44. // go over each (in priority order, as determined by the whole priority tree chaos),
  45. // and decide which we have tokens for, and how many tokens.
  46. // Writing on stream X requires that we have tokens on the
  47. // stream 0 (the conn-as-a-whole stream) as well as stream X.
  48. // So: find the highest priority stream X, then see: do we
  49. // have tokens for X? Let's say we have N_X tokens. Then we should
  50. // write MIN(N_X, TOKENS(conn-wide-tokens)).
  51. //
  52. // Any tokens left over? Repeat. Well, not really... the
  53. // repeat will happen via the next call to
  54. // scheduleFrameWrite. So keep a HEAP (priqueue) of which
  55. // streams to write to.
  56. // TODO: proper scheduler
  57. wm := ws.slice[0]
  58. // shift it all down. kinda lame. will be removed later anyway.
  59. copy(ws.slice, ws.slice[1:])
  60. ws.slice[len(ws.slice)-1] = frameWriteMsg{}
  61. ws.slice = ws.slice[:len(ws.slice)-1]
  62. return wm
  63. }