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