ボンジュール・マドモアゼル

本サイトの情報は自己責任にてご利用下さい。

[Inside COM] Inside COM 第8章 コンポーネントの再利用:包含と集約

 
Inside COM AGGRGATECMPNT2 P177-P178

//
// Constructor
//
CB::CB(IUnknown* pUnknownOuter)
: m_cRef(1)
{
    ::InterlockedIncrement(&g_cComponents) ;

    if (pUnknownOuter == NULL)
    {
        trace("Not aggregating; delegate to nondelegating IUnknown.") ;
        m_pUnknownOuter = reinterpret_cast<IUnknown*>
                          (static_cast<INondelegatingUnknown*>
                          (this)) ;
    }
    else
    {
        trace("Aggregating; delegate to outer IUnknown.") ;
        m_pUnknownOuter = pUnknownOuter ;
    }
}


Inside COM AGGRGATECMPNT2 P179-P180

//
// IClassFactory implementation
//
HRESULT __stdcall CFactory::CreateInstance(IUnknown* pUnknownOuter,
                                       const IID& iid,
                                       void** ppv)
{
    // Aggregate only if the requested iid is IID_IUnknown.
    if ((pUnknownOuter != NULL) && (iid != IID_IUnknown))
    {
        return CLASS_E_NOAGGREGATION ;
    }

    // Create component.
    CB* pB = new CB(pUnknownOuter) ; 
    if (pB == NULL)
    {
        return E_OUTOFMEMORY ;
    }

    // Get the requested interface.
    HRESULT hr = pB->NondelegatingQueryInterface(iid, ppv) ;
    pB->NondelegatingRelease() ;
    return hr ;
}
CreateInstance 関数を見ると、コンポーネント CB を集約せずに生成する際、 IID_IUnknown を要求すると、static_cast<INondelegatingUnknown*>(this) が返される。これは非委譲 unknown vptr である。したがって、この返されたポインタを使うと、集約されていないコンポーネントでも非委譲 unknown を直接呼び出せることになる。

しかし、これは本書の157頁 「図8-5 集約されていないコンポーネントでは、委譲unknownから非委譲unknownに呼び出しが委譲される」と話がかみ合わない。問題ないか。

また、非委譲 unknown を直接呼び出す場合と、 pIY->QueryInterface(IID_IUnknown, ppv); のように委譲 unknown を呼び出す場合では、 IID_Unknown を要求した際、返されるポインタは一致するのか。
3.2.1 一定のIUnknownの取得
...コンポーネントのインスタンスにIUnknownを要求すると、どのインタフェースを介して要求しても、同じポインタ値が返される。

に違反してるのではないか。疑問である。

【追記】
疑問が解消した。次のふたつの誤解があった。
  1. QueryInterface に、IID_IUnknown を要求したら、必ず IUnknown の vtbl を指す vptr を返さなければいけない(サンプルでいえば、委譲 unknown を返さなければならない)と誤解した。
  2. 集約オブジェクトとして使用しない場合、 IID_IUnknown インタフェースポインタから、呼ばれる QueryInterface と、IID_IY インタフェースポインタから呼ばれる QueryInterface は、異なる関数である(ここまでは正しい)。そこから、戻り値までも異なるものと誤解した。
結論としては、集約されないコンポーネントとして使用する場合、QueryInterfaceIID_IUnknown を要求すると、一貫して、INondelegatingUnknown の vtbl を指す vptr を返している。この vptr は、static_cast<INondelegatingUnknown*>(this) である。

集約されていないコンポーネント


なお、

つまり、内側のコンポーネントが集約されていない場合は、 委譲(delegating)unknown非委譲unknownに呼び出しを委譲する。
Inside COM 156頁 8.3.5

青字は私の補足。内側のコンポーネントが集約されていない場合、クライアントが、IID_Unknown インタフェースポインタを使う場合には、非委譲unknownが直接呼び出される。

[用語] 信頼性 と 可用性

 
信頼性と可用性の違い、今までよくわからなかったけど。。
「『信頼性reliability』と『可用性availability』の違いがよくわからない」と書いていたのを読んだのだけれど、今日昼飯を買いに行く途中でたとえを思いついた。

「頼んだ仕事は必ずきちんと仕上げてくる」というのがhigh reliability。
「いつどんな時に仕事を頼んでも引き受けてくれる」というのがhigh availability。

引用
http://blog.practical-scheme.net/shiro/20090529-reliability-and-availability
(2009/05/29 17:16:05 PDT reliabilityとavailability)