]> Sergey Matveev's repositories - btrtrc.git/blob - worse-conns.go
Abstract worseConn comparisons and add tests
[btrtrc.git] / worse-conns.go
1 package torrent
2
3 import (
4         "container/heap"
5         "fmt"
6         "time"
7         "unsafe"
8
9         "github.com/anacrolix/multiless"
10 )
11
12 type worseConnInput struct {
13         Useful             bool
14         LastHelpful        time.Time
15         CompletedHandshake time.Time
16         PeerPriority       peerPriority
17         PeerPriorityErr    error
18         Pointer            uintptr
19 }
20
21 func worseConnInputFromPeer(p *Peer) worseConnInput {
22         ret := worseConnInput{
23                 Useful:             p.useful(),
24                 LastHelpful:        p.lastHelpful(),
25                 CompletedHandshake: p.completedHandshake,
26                 Pointer:            uintptr(unsafe.Pointer(p)),
27         }
28         ret.PeerPriority, ret.PeerPriorityErr = p.peerPriority()
29         return ret
30 }
31
32 func worseConn(_l, _r *Peer) bool {
33         return worseConnInputFromPeer(_l).Less(worseConnInputFromPeer(_r))
34 }
35
36 func (l worseConnInput) Less(r worseConnInput) bool {
37         less, ok := multiless.New().Bool(
38                 l.Useful, r.Useful).CmpInt64(
39                 l.LastHelpful.Sub(r.LastHelpful).Nanoseconds()).CmpInt64(
40                 l.CompletedHandshake.Sub(r.CompletedHandshake).Nanoseconds()).LazySameLess(
41                 func() (same, less bool) {
42                         same = l.PeerPriorityErr != nil || r.PeerPriorityErr != nil || l.PeerPriority == r.PeerPriority
43                         less = l.PeerPriority < r.PeerPriority
44                         return
45                 }).Uintptr(
46                 l.Pointer, r.Pointer,
47         ).LessOk()
48         if !ok {
49                 panic(fmt.Sprintf("cannot differentiate %#v and %#v", l, r))
50         }
51         return less
52 }
53
54 type worseConnSlice struct {
55         conns []*PeerConn
56 }
57
58 var _ heap.Interface = &worseConnSlice{}
59
60 func (me worseConnSlice) Len() int {
61         return len(me.conns)
62 }
63
64 func (me worseConnSlice) Less(i, j int) bool {
65         return worseConn(&me.conns[i].Peer, &me.conns[j].Peer)
66 }
67
68 func (me *worseConnSlice) Pop() interface{} {
69         i := len(me.conns) - 1
70         ret := me.conns[i]
71         me.conns = me.conns[:i]
72         return ret
73 }
74
75 func (me *worseConnSlice) Push(x interface{}) {
76         me.conns = append(me.conns, x.(*PeerConn))
77 }
78
79 func (me worseConnSlice) Swap(i, j int) {
80         me.conns[i], me.conns[j] = me.conns[j], me.conns[i]
81 }