00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00048 #ifndef COMSTL_INCL_COMSTL_UTIL_HPP_ACYCLIC_CONNECTOR
00049 #define COMSTL_INCL_COMSTL_UTIL_HPP_ACYCLIC_CONNECTOR
00050 
00051 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00052 # define COMSTL_VER_COMSTL_UTIL_HPP_ACYCLIC_CONNECTOR_MAJOR     1
00053 # define COMSTL_VER_COMSTL_UTIL_HPP_ACYCLIC_CONNECTOR_MINOR     2
00054 # define COMSTL_VER_COMSTL_UTIL_HPP_ACYCLIC_CONNECTOR_REVISION  7
00055 # define COMSTL_VER_COMSTL_UTIL_HPP_ACYCLIC_CONNECTOR_EDIT      21
00056 #endif 
00057 
00058 
00059 
00060 
00061 
00062 #ifndef COMSTL_INCL_COMSTL_H_COMSTL
00063 # include <comstl/comstl.h>
00064 #endif 
00065 #ifndef COMSTL_INCL_COMSTL_UTIL_HPP_OBJECT_FUNCTIONS
00066 # include <comstl/util/object_functions.h>
00067 #endif 
00068 #ifndef STLSOFT_INCL_STLSOFT_SYNCH_HPP_LOCK_SCOPE
00069 # include <stlsoft/synch/lock_scope.hpp>
00070 #endif 
00071 
00072 
00073 
00074 
00075 
00076 #ifndef _COMSTL_NO_NAMESPACE
00077 # if defined(_STLSOFT_NO_NAMESPACE) || \
00078      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00079 
00080 namespace comstl
00081 {
00082 # else
00083 
00084 
00085 namespace stlsoft
00086 {
00087 
00088 namespace comstl_project
00089 {
00090 
00091 # endif 
00092 #endif 
00093 
00094 
00095 
00096 
00097 
00100 #ifdef STLSOFT_DOCUMENTATION_SKIP_SECTION
00101 struct IAcyclicSide
00102     : public IUnknown
00103 #else 
00104 DECLARE_INTERFACE_(IAcyclicSide, IUnknown)
00105 #endif 
00106 {
00109     STDMETHOD_(void, Clear)() PURE;
00117     STDMETHOD(QueryPeer)(THIS_ REFIID riid, void **ppv) PURE;
00118 
00120     static REFIID iid()
00121     {
00122         static IID s_iid = { 0x8D5D0B0A, 0x4429, 0x4be1, { 0x8C, 0x00, 0xDE, 0xE0, 0xA8, 0xFF, 0xD0, 0xAF } };
00123 
00124         return s_iid;
00125     }
00126 };
00127 
00150 template <ss_typename_param_k MX>
00151 class acyclic_connector
00152 {
00155 public:
00156     typedef MX                      mutex_type;
00157 private:
00158     typedef acyclic_connector<MX>   connector_type;
00159 public:
00160     typedef acyclic_connector<MX>   class_type;
00161 private:
00162     class side
00163         : public IAcyclicSide
00164     {
00167     public:
00168         typedef side            class_type;
00170 
00173     public:
00174         ss_explicit_k side(connector_type &connector, LPUNKNOWN peer, IAcyclicSide **side)
00175             : m_connector(connector)
00176             , m_peer(peer)
00177             , m_refCount(1)
00178         {
00179             COMSTL_ASSERT(NULL != side);
00180             *side = this;
00181         }
00183 
00186     public:
00187         STDMETHOD_(ULONG, AddRef)()
00188         {
00189             return ++m_refCount;
00190         }
00191         STDMETHOD_(ULONG, Release)()
00192         {
00193             class_type  &other  =   (this == &m_connector.m_left) ? m_connector.m_right : m_connector.m_left;
00194 
00195             if(0 == --m_refCount)
00196             {
00197                 m_peer = NULL;
00198 
00199                 if(0 == other.m_refCount)
00200                 {
00201                     delete &m_connector;
00202 
00203                     return 0;
00204                 }
00205             }
00206 
00207             return m_refCount;
00208         }
00209         STDMETHOD(QueryInterface)(REFIID riid, void **ppv)
00210         {
00211             if( IID_IUnknown == riid ||
00212                 IAcyclicSide::iid() == riid)
00213             {
00214                 *ppv = static_cast<LPUNKNOWN>(this);
00215                 static_cast<LPUNKNOWN>(*ppv)->AddRef();
00216                 return S_OK;
00217             }
00218 
00219             return E_NOINTERFACE;
00220         }
00222 
00225     public:
00226         STDMETHOD_(void, Clear)()
00227         {
00228             stlsoft::lock_scope<mutex_type> lock(m_connector.m_mx);
00229 
00230             m_peer = NULL;
00231         }
00232         STDMETHOD(QueryPeer)(THIS_ REFIID riid, void **ppv)
00233         {
00234             COMSTL_ASSERT(NULL != ppv);
00235 
00236             stlsoft::lock_scope<mutex_type> lock(m_connector.m_mx);
00237             class_type                      &other  =   (this == &m_connector.m_left) ? m_connector.m_right : m_connector.m_left;
00238 
00239             if(NULL == other.m_peer)
00240             {
00241                 return E_POINTER;
00242             }
00243             else
00244             {
00245                 return other.m_peer->QueryInterface(riid, ppv);
00246             }
00247         }
00249 
00252     private:
00253         connector_type  &m_connector;
00254         LPUNKNOWN       m_peer;
00255         LONG            m_refCount;
00257     };
00258     friend class side;
00260 
00263 public:
00264     acyclic_connector(  LPUNKNOWN       leftPeer
00265                     ,   IAcyclicSide    **leftSide
00266                     ,   LPUNKNOWN       rightPeer
00267                     ,   IAcyclicSide    **rightSide);
00268 private:
00269     ~acyclic_connector() stlsoft_throw_0();
00271 
00274 private:
00275     class_type& get_this_();
00277 
00280 private:
00281     side        m_left;
00282     side        m_right;
00283     mutex_type  m_mx;
00285 
00288 private:
00289     acyclic_connector(class_type const& rhs);
00290     class_type& operator =(class_type const& rhs);
00292 };
00293 
00294 
00295 
00296 
00297 
00298 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00299 
00300 
00301 
00302 #if 0
00303 template <ss_typename_param_k MX>
00304 inline acyclic_connector<MX>::side::side(connector_type &connector, LPUNKNOWN peer, IAcyclicSide **side)
00305     : m_connector(connector)
00306     , m_peer(peer)
00307     , m_refCount(1)
00308 {
00309     COMSTL_ASSERT(NULL != side);
00310     *side = this;
00311 }
00312 
00313 template <ss_typename_param_k MX>
00314 inline STDMETHODIMP_(ULONG) acyclic_connector<MX>::side::AddRef()
00315 {
00316     return ++m_refCount;
00317 }
00318 
00319 template <ss_typename_param_k MX>
00320 inline STDMETHODIMP_(ULONG) acyclic_connector<MX>::side::Release()
00321 {
00322     class_type  &other  =   (this == &m_connector.m_left) ? m_connector.m_right : m_connector.m_left;
00323 
00324     if( 0 == --m_refCount &&
00325         0 == other.m_refCount)
00326     {
00327         delete &m_connector;
00328 
00329         return 0;
00330     }
00331 
00332     return m_refCount;
00333 }
00334 
00335 template <ss_typename_param_k MX>
00336 inline STDMETHODIMP acyclic_connector<MX>::side::QueryInterface(REFIID riid, void **ppv)
00337 {
00338     if( IID_IUnknown == riid ||
00339         IAcyclicSide::iid() == riid)
00340     {
00341         *ppv = static_cast<LPUNKNOWN>(this);
00342         static_cast<LPUNKNOWN>(*ppv)->AddRef();
00343         return S_OK;
00344     }
00345 
00346     return E_INTERFACE;
00347 }
00348 #endif 
00349 
00350 #if 0
00351 template <ss_typename_param_k MX>
00352 inline STDMETHODIMP_(void) acyclic_connector<MX>::side::Clear()
00353 {
00354     stlsoft::lock_scope<mutex_type> lock(m_mx);
00355 
00356     m_peer = NULL;
00357 }
00358 
00359 template <ss_typename_param_k MX>
00360 inline STDMETHODIMP acyclic_connector<MX>::side::QueryPeer(THIS_ REFIID riid, void **ppv)
00361 {
00362     COMSTL_ASSERT(NULL != ppv);
00363 
00364     stlsoft::lock_scope<mutex_type> lock(m_mx);
00365 
00366     if(NULL == m_peer)
00367     {
00368         return E_POINTER;
00369     }
00370     else
00371     {
00372         return m_peer->QueryInterface(riid, ppv);
00373     }
00374 }
00375 #endif 
00376 
00377 
00378 
00379 template <ss_typename_param_k MX>
00380 inline acyclic_connector<MX>::acyclic_connector(LPUNKNOWN       leftPeer
00381                                             ,   IAcyclicSide    **leftSide
00382                                             ,   LPUNKNOWN       rightPeer
00383                                             ,   IAcyclicSide    **rightSide)
00384     : m_left(get_this_(), leftPeer, leftSide)
00385     , m_right(get_this_(), rightPeer, rightSide)
00386     , m_mx()
00387 {
00388     COMSTL_MESSAGE_ASSERT("Acyclic connector cannot be initialised with null pointers", NULL != leftPeer);
00389     COMSTL_MESSAGE_ASSERT("Acyclic connector cannot be initialised with null pointers", NULL != rightPeer);
00390     COMSTL_MESSAGE_ASSERT("Acyclic connector cannot be initialised with null pointers", NULL != leftSide);
00391     COMSTL_MESSAGE_ASSERT("Acyclic connector cannot be initialised with null pointers", NULL != rightSide);
00392 #if 0
00393 
00394     HRESULT hr;
00395 
00396     hr = get_object_identity(left, &m_left);
00397     if(FAILED(hr))
00398     {
00399 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00400         STLSOFT_THROW_X(com_exception("Could not acquire left-side identity", hr));
00401 #endif 
00402     }
00403     else
00404     {
00405         hr = get_object_identity(right, &m_right);
00406 
00407         if(FAILED(hr))
00408         {
00409             m_left->Release();
00410 
00411 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00412             STLSOFT_THROW_X(com_exception("Could not acquire right-side identity", hr));
00413 #else 
00414             m_left = NULL;
00415 #endif 
00416         }
00417     }
00418 #endif 
00419 }
00420 
00421 template <ss_typename_param_k MX>
00422 inline acyclic_connector<MX>::~acyclic_connector() stlsoft_throw_0()
00423 {}
00424 
00425 template <ss_typename_param_k MX>
00426 inline ss_typename_type_ret_k acyclic_connector<MX>::class_type& acyclic_connector<MX>::get_this_()
00427 {
00428     return *this;
00429 }
00430 
00431 #endif 
00432 
00433 
00434 
00435 #ifndef _COMSTL_NO_NAMESPACE
00436 # if defined(_STLSOFT_NO_NAMESPACE) || \
00437      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00438 } 
00439 # else
00440 } 
00441 } 
00442 # endif 
00443 #endif 
00444 
00445 
00446 
00447 #endif 
00448 
00449