Re: AddRef/Release side effects - is this ok?
Igor R. wrote:
No. I just didn't elaborate on how the signalling subsystem works.
Disconnecting "slot" (i.e. the callback functor) from "signal" doesn't
cause an immediate (synchronous) destruction of the slot - this
wouldn't be thread-safe. The async. callback may be already in
progress, because it might be started just before I disconnected the
signal, and it would end gracefully without crash, as the wrapper is
still afloat -- thanks to CComPtr bound to the slot. Now when the
async.callback ends - and the slot is already disconnected - the
signalling subsystem disposes the disconnected slot, and CComPtr bound
to it dies.
I think your scheme won't work, but for a different reason than the one
you are concerned about.
The whole proxy issue is a red herring. While it's true that you don't
see every single AddRef and Release call made on a proxy, you do know
that, as long as at least one proxy is alive, there is a strong
reference on your object; when all the proxies are destroyed, they'll
release all those references. So the count will be above
internal_refcount with the proxies (or, in fact, direct clients), and
will go down to internal_refcount once all clients disconnect.
But there's a different problem. As those CComPtr instances you use for
"internal" references are copied (at the very least, the temporary
instance you pass to bind() must be copied), there will be superfluous
AddRef/Release pairs of calls. This will briefly raise the refcount
above internal_refcount, then drop it back down. In your scheme, this
will prematurely trigger event disconnection logic.
Here's one way to work around this difficulty. Create two C++ classes -
one is what you have now sans slots, the other containing slots and a
trivial IUnknown implementation with its own refcount (let's call it
event sink). The sink would hold a regular C++ pointer to the main
class, and would AddRef it exactly once in its constructor and Release
exactly once when its own refcount reaches zero. You may also find it
convenient to forward actual events to the main class, so that all the
business logic is concentrated in one place. The main class may create
the sink class on the heap, or hold it as a data member. The main class
would disconnect events when its reference count drops to 1, and destroy
itself when it drops to 0.
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925