运行 Object Table 是如何实现弱引用的?
How does Running Object Table implement weak references?
当你在 运行 对象 Table 中注册一个带有零标志的 COM 对象(请求弱引用)时,ROT 将引用计数递增 1。获取对象的行为来自 ROT 的引用计数会增加 1。一旦该对象被释放,该对象就会保持活动状态,引用计数至少为 1。它在 ROT 中的注册也不会在检索时被神奇地撤销。
怎么这么弱?这与强注册有何不同?
强注册遵循相同的模式 - 注册和检索都会将引用计数递增 1。
ROTreturns指向公寓内客户端的接口指针不是代理; ROT 无法知道我已经释放了检索到的接口指针。
真正从 ROT 行为中移除不仅取决于 ROTFLAGS_REGISTRATIONKEEPSALIVE
标志,而且还取决于(以及如何)实现您的对象 IExternalConnection
(仅针对@IInspectable 的特别说明 - 是的,所有这些都没有记录,不受支持,可以更改 - 所以请不要阅读更多)。
当我们在 ROT com 中注册对象时,总是向他查询 IExternalConnection
接口。如果对象未实现它 - 使用默认实现。
万一 ROTFLAGS_REGISTRATIONKEEPSALIVE
已经在注册时间 IExternalConnection::AddConnection
打电话了。所以我们已经有 1 个外部连接。没有 ROTFLAGS_REGISTRATIONKEEPSALIVE
- 未调用此方法。
每当有人打电话给 IRunningObjectTable::GetObject
(!从另一间公寓)时,CRemoteUnknown::RemAddRef
就会在我们的过程。此方法调用 IExternalConnection::AddConnection
仅当 我们注册 没有 ROTFLAGS_REGISTRATIONKEEPSALIVE
标志。
每次我们最终 Release
对象(!在代理上,从之前的 GetObject
调用 ) - CRemoteUnknown::RemReleaseWorker
在我们的本地进程中调用。并在对象上 IExternalConnection::ReleaseConnection
only 内部调用 no ROTFLAGS_REGISTRATIONKEEPSALIVE
. IExternalConnection
的默认实现调用 CStdMarshal::Disconnect
-> InternalIrotRevoke
当外部引用(不是全部对象引用)达到 0 和 fLastReleaseCloses == TRUE
- 结果我们的对象从 ROT 中撤销。但是如果我们自己实现 IExternalConnection
我们可以调用或不调用 CoDisconnectObject
所以我们可以从 ROT 中被撤销或不被撤销。
最后,当我们直接或间接调用 IRunningObjectTable::Revoke
com call IExternalConnection::ReleaseConnection
if 时,我们注册 with ROTFLAGS_REGISTRATIONKEEPSALIVE
.
所以结论:
如果我们用ROTFLAGS_REGISTRATIONKEEPSALIVE
注册-IExternalConnection::AddConnection
只会在注册时被调用一次(真的可以调用n+1
时间和n
时间-ReleaseConnection
- 但所有这些都在 IRunningObjectTable::Register
调用中。)。当有人从 ROT 获得我们的对象时 - 我们将不通知。最后 IExternalConnection::ReleaseConnection
也只会在我们调用 IRunningObjectTable::Revoke
.
时被调用一次
另一方面,如果我们不使用 ROTFLAGS_REGISTRATIONKEEPSALIVE
标志 - IExternalConnection
方法将 不被调用 Register
和 Revoke
。但它将在 IRunningObjectTable::GetObject
和最终 Release
上 多次调用 ( 在对象代理上).如果我们没有自己实现 IExternalConnection
或在外部引用达到 0 和 fLastReleaseCloses
时调用 CoDisconnectObject
- 我们将从 ROT 中移除。但我们释放 not call CoDisconnectObject
(在这种情况下,行为就像我们使用 ROTFLAGS_REGISTRATIONKEEPSALIVE
)或调用它在某种条件下。
优点 - 我们可以跟踪每个对象的使用情况,以防没有 ROTFLAGS_REGISTRATIONKEEPSALIVE
标志,并自行决定在外部引用达到或不达到 0 时是否需要断开连接。
和最后一个 - 如果我们从我们呼叫 IRunningObjectTable::Register
的同一公寓呼叫 IRunningObjectTable::GetObject
- 我们得到的不是代理,而是直接对象指针。在这种情况下当然不会调用 IExternalConnection
方法
当你在 运行 对象 Table 中注册一个带有零标志的 COM 对象(请求弱引用)时,ROT 将引用计数递增 1。获取对象的行为来自 ROT 的引用计数会增加 1。一旦该对象被释放,该对象就会保持活动状态,引用计数至少为 1。它在 ROT 中的注册也不会在检索时被神奇地撤销。
怎么这么弱?这与强注册有何不同?
强注册遵循相同的模式 - 注册和检索都会将引用计数递增 1。
ROTreturns指向公寓内客户端的接口指针不是代理; ROT 无法知道我已经释放了检索到的接口指针。
真正从 ROT 行为中移除不仅取决于 ROTFLAGS_REGISTRATIONKEEPSALIVE
标志,而且还取决于(以及如何)实现您的对象 IExternalConnection
(仅针对@IInspectable 的特别说明 - 是的,所有这些都没有记录,不受支持,可以更改 - 所以请不要阅读更多)。
当我们在 ROT com 中注册对象时,总是向他查询 IExternalConnection
接口。如果对象未实现它 - 使用默认实现。
万一 ROTFLAGS_REGISTRATIONKEEPSALIVE
已经在注册时间 IExternalConnection::AddConnection
打电话了。所以我们已经有 1 个外部连接。没有 ROTFLAGS_REGISTRATIONKEEPSALIVE
- 未调用此方法。
每当有人打电话给 IRunningObjectTable::GetObject
(!从另一间公寓)时,CRemoteUnknown::RemAddRef
就会在我们的过程。此方法调用 IExternalConnection::AddConnection
仅当 我们注册 没有 ROTFLAGS_REGISTRATIONKEEPSALIVE
标志。
每次我们最终 Release
对象(!在代理上,从之前的 GetObject
调用 ) - CRemoteUnknown::RemReleaseWorker
在我们的本地进程中调用。并在对象上 IExternalConnection::ReleaseConnection
only 内部调用 no ROTFLAGS_REGISTRATIONKEEPSALIVE
. IExternalConnection
的默认实现调用 CStdMarshal::Disconnect
-> InternalIrotRevoke
当外部引用(不是全部对象引用)达到 0 和 fLastReleaseCloses == TRUE
- 结果我们的对象从 ROT 中撤销。但是如果我们自己实现 IExternalConnection
我们可以调用或不调用 CoDisconnectObject
所以我们可以从 ROT 中被撤销或不被撤销。
最后,当我们直接或间接调用 IRunningObjectTable::Revoke
com call IExternalConnection::ReleaseConnection
if 时,我们注册 with ROTFLAGS_REGISTRATIONKEEPSALIVE
.
所以结论:
如果我们用ROTFLAGS_REGISTRATIONKEEPSALIVE
注册-IExternalConnection::AddConnection
只会在注册时被调用一次(真的可以调用n+1
时间和n
时间-ReleaseConnection
- 但所有这些都在 IRunningObjectTable::Register
调用中。)。当有人从 ROT 获得我们的对象时 - 我们将不通知。最后 IExternalConnection::ReleaseConnection
也只会在我们调用 IRunningObjectTable::Revoke
.
另一方面,如果我们不使用 ROTFLAGS_REGISTRATIONKEEPSALIVE
标志 - IExternalConnection
方法将 不被调用 Register
和 Revoke
。但它将在 IRunningObjectTable::GetObject
和最终 Release
上 多次调用 ( 在对象代理上).如果我们没有自己实现 IExternalConnection
或在外部引用达到 0 和 fLastReleaseCloses
时调用 CoDisconnectObject
- 我们将从 ROT 中移除。但我们释放 not call CoDisconnectObject
(在这种情况下,行为就像我们使用 ROTFLAGS_REGISTRATIONKEEPSALIVE
)或调用它在某种条件下。
优点 - 我们可以跟踪每个对象的使用情况,以防没有 ROTFLAGS_REGISTRATIONKEEPSALIVE
标志,并自行决定在外部引用达到或不达到 0 时是否需要断开连接。
和最后一个 - 如果我们从我们呼叫 IRunningObjectTable::Register
的同一公寓呼叫 IRunningObjectTable::GetObject
- 我们得到的不是代理,而是直接对象指针。在这种情况下当然不会调用 IExternalConnection
方法