Skip to content

Commit 13883e4

Browse files
committed
Don't have a separate refcount for calls vs. Clients.
This will simplify transitioning to using the rc package for refcounting. Right now there is a bug where one of the tests is failing with an error about multiple shutdowns -- I think this is likely equivalent to capnproto#348 (the done channel is gone), but it seems to be deterministic now.
1 parent 38fbdcf commit 13883e4

File tree

1 file changed

+8
-19
lines changed

1 file changed

+8
-19
lines changed

capability.go

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,6 @@ type clientHook struct {
138138
// Place for callers to attach arbitrary metadata to the client.
139139
metadata Metadata
140140

141-
// done is closed when refs == 0 and calls == 0.
142-
done chan struct{}
143-
144141
state mutex.Mutex[clientHookState]
145142
}
146143

@@ -149,7 +146,6 @@ type clientHookState struct {
149146
resolved chan struct{}
150147

151148
refs int // how many open Clients reference this clientHook
152-
calls int // number of outstanding ClientHook accesses
153149
resolvedHook *clientHook // valid only if resolved is closed
154150
}
155151

@@ -164,7 +160,6 @@ func NewClient(hook ClientHook) Client {
164160
}
165161
h := &clientHook{
166162
ClientHook: hook,
167-
done: make(chan struct{}),
168163
metadata: *NewMetadata(),
169164
state: mutex.New(clientHookState{
170165
resolved: closedSignal,
@@ -199,7 +194,6 @@ func newPromisedClient(hook ClientHook) (Client, *clientPromise) {
199194
}
200195
h := &clientHook{
201196
ClientHook: hook,
202-
done: make(chan struct{}),
203197
metadata: *NewMetadata(),
204198
state: mutex.New(clientHookState{
205199
resolved: make(chan struct{}),
@@ -228,17 +222,19 @@ func (c Client) startCall() (hook ClientHook, resolved, released bool, finish fu
228222
if c.h == nil {
229223
return nil, true, false, func() {}
230224
}
231-
l.Value().calls++
225+
l.Value().refs++
232226
isResolved := l.Value().isResolved()
233227
l.Unlock()
234228
savedHook := c.h
235229
return savedHook.ClientHook, isResolved, false, func() {
230+
shutdown := func() {}
236231
savedHook.state.With(func(s *clientHookState) {
237-
s.calls--
238-
if s.refs == 0 && s.calls == 0 {
239-
close(savedHook.done)
232+
s.refs--
233+
if s.refs == 0 {
234+
shutdown = savedHook.Shutdown
240235
}
241236
})
237+
shutdown()
242238
}
243239
})
244240
}
@@ -653,12 +649,8 @@ func (c Client) Release() {
653649
cl.Unlock()
654650
return
655651
}
656-
if hl.Value().calls == 0 {
657-
close(h.done)
658-
}
659652
hl.Unlock()
660653
cl.Unlock()
661-
<-h.done
662654
h.Shutdown()
663655
c.GetFlowLimiter().Release()
664656
}
@@ -735,7 +727,6 @@ func (cp *clientPromise) Fulfill(c Client) {
735727
// references to be dropped, and then shuts down the hook. The caller
736728
// must have previously invoked cp.fulfill().
737729
func (cp *clientPromise) shutdown() {
738-
<-cp.h.done
739730
cp.h.Shutdown()
740731
}
741732

@@ -770,9 +761,8 @@ func (cp *clientPromise) fulfill(c Client) {
770761
}
771762

772763
// Client still had references, so we're responsible for shutting it down.
773-
if l.Value().calls == 0 {
774-
close(cp.h.done)
775-
}
764+
defer cp.h.Shutdown()
765+
776766
rh, l = resolveHook(cp.h, l) // swaps mutex on cp.h for mutex on rh
777767
if rh != nil {
778768
l.Value().refs += refs
@@ -1008,7 +998,6 @@ func ErrorClient(e error) Client {
1008998
// Avoid NewClient because it can set a finalizer.
1009999
h := &clientHook{
10101000
ClientHook: errorClient{e},
1011-
done: make(chan struct{}),
10121001
metadata: *NewMetadata(),
10131002
state: mutex.New(clientHookState{
10141003
resolved: closedSignal,

0 commit comments

Comments
 (0)