This repository has been archived by the owner on Nov 27, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathpoller.go
115 lines (104 loc) · 2.53 KB
/
poller.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package dnssd
import "sync"
type pollable interface {
init(uintptr) (uintptr, error)
handleError(error)
}
type pollServerOp struct {
p pollable
ref uintptr
fd int
}
var pollServer pollServerState
type pollServerState struct {
platformPollServerState
m struct {
external, internal sync.Mutex
}
shared struct {
ref uintptr
fd int
}
pollables map[pollable]*pollServerOp
pollSlicesUpToDate bool
sharedPollableElements []*pollServerOp
uniquePollableElements []*pollServerOp
}
func (s *pollServerState) startOp(p pollable) error {
s.m.external.Lock()
if s.pollables == nil {
s.pollables = make(map[pollable]*pollServerOp)
}
s.stopPoll()
s.m.internal.Lock()
defer func() {
s.m.internal.Unlock()
s.startPoll()
s.m.external.Unlock()
}()
if _, present := s.pollables[p]; present {
return ErrStarted
}
s.establishSharedConnection()
ref, err := p.init(s.shared.ref)
if err != nil {
return err
}
fd := 0
if s.shared.ref == 0 {
fd = refSockFd(&ref)
}
s.addPollOp(&pollServerOp{p: p, ref: ref, fd: fd})
return nil
}
func (s *pollServerState) stopOp(p pollable) error {
s.m.external.Lock()
defer s.m.external.Unlock()
s.stopPoll()
s.m.internal.Lock()
s.removePollOp(p)
s.m.internal.Unlock()
s.startPoll()
return nil
}
func (s *pollServerState) sharedAndUniquePollables() ([]*pollServerOp, []*pollServerOp) {
if s.pollSlicesUpToDate {
return s.sharedPollableElements, s.uniquePollableElements
}
s.sharedPollableElements, s.uniquePollableElements = nil, nil
for _, op := range s.pollables {
if op.fd > 0 {
s.uniquePollableElements = append(s.uniquePollableElements, op)
} else {
s.sharedPollableElements = append(s.sharedPollableElements, op)
}
}
s.pollSlicesUpToDate = true
return s.sharedPollableElements, s.uniquePollableElements
}
func (s *pollServerState) removePollOp(p pollable) {
if op, present := s.pollables[p]; present {
deallocateRef(&op.ref)
delete(s.pollables, p)
s.sharedPollableElements, s.uniquePollableElements = nil, nil
s.pollSlicesUpToDate = false
}
}
func (s *pollServerState) addPollOp(p *pollServerOp) {
s.pollables[p.p] = p
s.sharedPollableElements, s.uniquePollableElements = nil, nil
s.pollSlicesUpToDate = false
}
func (s *pollServerState) establishSharedConnection() {
if len(s.pollables) == 0 && s.shared.ref == 0 {
if err := createConnection(&s.shared.ref); err != nil {
_ = err // TODO: do something with err?
s.shared.ref = 0
} else {
s.shared.fd = refSockFd(&s.shared.ref)
if s.shared.fd < 0 {
panic("bad fd")
}
}
}
}