@Jon_Shier can you provide a bit of sample code for the TimerPublisher
case not cancelling? I can take a look.
Let me try to clear up some of the Cancellable
part.
Publisher
is almost always a struct
. When you subscribe something to it, the Publisher
will create a Subscription
(almost always a class
) and send it to the Subscriber
. This is a ref type because it's stateful - what's the pending demand, what have I sent, etc.
Since the Publisher
created a reference out of thin air, something needs to retain it. Since the Subscription
is sent to the Subscriber
, it makes sense for the Subscriber
to be responsible for it. Therefore, a Subscriber
will maintain a reference to its upstream like this:
var upstream: Subscription?
Operators, being in the middle, need to also maintain a reference to their downstream, because they are sending them values:
let downstream: Downstream
(a property of the Subscription
that the operator sends to its own Subscriber
, of course)
It is not a weak reference for performance reasons. Sending values downstream is the "fast path" we optimize for. Having to always look up a weak reference is very expensive. So -- we have two retains: one up, one down. We need to break a cycle at some point. upstream
can be set to nil
upon cancel
, but when to call it? Completion is one obvious point, but what about indefinite publishers like NotificationCenter
? Should it be always required to call cancel
or can we do it automatically?
At the termination of a stream, a Subscriber
is holding on to its upstream strongly, keeping the subscriptions alive. If the stream does not finish, then just throwing away the last reference results in a leak.
To fix this, we could have weak references at every step -- but it is expensive, as I mentioned. We only need one point to break the cycle. We chose AnyCancellable
as that point. It holds onto the Cancellable
, but when it itself is deallocated, it calls cancel
, resulting in each step along the chain throwing away any associated memory and allowing proper teardown to happen.
Hope this helps.