运行对象表如何实现弱引用?

时间:2016-11-19 17:09:17

标签: winapi com win32com running-object-table

当您在运行对象表中使用零标志(请求弱参考)注册COM对象时,ROT将引用计数递增1.从ROT获取对象的行为将引用计数增加一个。一旦释放了该对象,该对象将保持活动状态,其引用次数至少为1。它在ROT中的注册也不会在检索时被神奇地撤销。

这有多弱?这与强势注册有何不同?

强注册遵循相同的模式 - 注册和检索都将引用计数递增1。

ROT返回公寓客户端的接口指针不是代理; ROT无法知道我已经释放了我检索到的接口指针。

1 个答案:

答案 0 :(得分:2)

真正从ROT行为中删除,不仅取决于ROTFLAGS_REGISTRATIONKEEPSALIVE标志,还取决于您的对象实现(以及如何)IExternalConnection

仅限@IInspectable的特别说明 - 是的,所有这些都是未记录的,不受支持的,可以更改 - 所以请不要阅读更多)。

当我们在ROT中注册对象时,总是向他查询IExternalConnection接口。如果对象没有实现它 - 使用默认实现。

以防 ROTFLAGS_REGISTRATIONKEEPSALIVE已在注册时IExternalConnection::AddConnection调用。所以我们已经有1个外部连接。没有ROTFLAGS_REGISTRATIONKEEPSALIVE - 此方法未被调用。

每当有人在我们的流程中调用IRunningObjectTable::GetObject!来自其他公寓)时调用CRemoteUnknown::RemAddRef。此方法仅在我们注册而不是 ROTFLAGS_REGISTRATIONKEEPSALIVE标记时调用IExternalConnection::AddConnection

每次我们最终Release对象(!on proxy,from previous GetObject call ) - CRemoteUnknown::RemReleaseWorker在我们的本地进程中调用。如果对象上的 ROTFLAGS_REGISTRATIONKEEPSALIVE,它会在内部调用IExternalConnection::ReleaseConnection 。名为CStdMarshal::Disconnect的{​​{3}}的默认实施 - > InternalIrotRevoke当外部引用(不是tottal对象引用)达到0和fLastReleaseCloses == TRUE时 - 结果我们的对象从ROT中撤销。但如果我们自己实施IExternalConnection,我们可以致电或不致电IExternalConnection,以便我们可以撤销或不撤销ROT。

最后当我们直接或间接致电CoDisconnectObject com来电话IRunningObjectTable::Revoke 如果我们将注册 ROTFLAGS_REGISTRATIONKEEPSALIVE

结论:

如果我们注册ROTFLAGS_REGISTRATIONKEEPSALIVE - IExternalConnection::ReleaseConnection,则只会在注册时调用一次(实际上可以称为n+1时间和n时间 - {{1} } - 但所有这些都在IExternalConnection::AddConnection内部调用。)。当有人从ROT获取我们的对象时 - 我们将未通知。当我们拨打IRunningObjectTable::Register时,最后IExternalConnection::ReleaseConnection也会被调用。

另一方面,如果我们不使用ReleaseConnection标记 - IRunningObjectTable::Revoke方法,则ROTFLAGS_REGISTRATIONKEEPSALIVERegister上的不会被称为。但在IExternalConnection和最终Revoke在对象代理上)多次调用。如果我们没有自己实施IRunningObjectTable::GetObject或在外部裁判达到0和Release时致电IExternalConnection,我们将从ROT中删除。但是我们可以免费不调用 CoDisconnectObject(在这种情况下,行为就像我们使用fLastReleaseCloses)或者说在某种情况下调用它。

优点 - 我们可以跟踪每个对象的使用情况,如果没有ROTFLAGS_REGISTRATIONKEEPSALIVE标志,并且当外部参考值达到0时,自我决定是否需要断开连接。

和最后一个 - 如果我们从我们称之为CoDisconnectObject的同一个公寓中调用IRunningObjectTable::GetObject - 我们没有代理,而是直接对象指针。在这种情况下,当然不会调用IRunningObjectTable::Register方法