VirtualBox

source: vbox/trunk/include/VBox/com/ptr.h@ 27607

Last change on this file since 27607 was 27607, checked in by vboxsync, 15 years ago

Main: remove templates for 'weak' com pointers which do nothing anyway

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.0 KB
Line 
1/** @file
2 * MS COM / XPCOM Abstraction Layer:
3 * Smart COM pointer classes declaration
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 *
26 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31#ifndef ___VBox_com_ptr_h
32#define ___VBox_com_ptr_h
33
34/* Make sure all the stdint.h macros are included - must come first! */
35#ifndef __STDC_LIMIT_MACROS
36# define __STDC_LIMIT_MACROS
37#endif
38#ifndef __STDC_CONSTANT_MACROS
39# define __STDC_CONSTANT_MACROS
40#endif
41
42#if !defined (VBOX_WITH_XPCOM)
43
44#include <atlbase.h>
45
46#ifndef _ATL_IIDOF
47# define _ATL_IIDOF(c) __uuidof(c)
48#endif
49
50#else /* !defined (VBOX_WITH_XPCOM) */
51
52#include <nsXPCOM.h>
53#include <nsIComponentManager.h>
54#include <nsCOMPtr.h>
55#include <ipcIService.h>
56#include <nsIServiceManagerUtils.h>
57#include <ipcCID.h>
58#include <ipcIDConnectService.h>
59
60// official XPCOM headers don't define it yet
61#define IPC_DCONNECTSERVICE_CONTRACTID \
62 "@mozilla.org/ipc/dconnect-service;1"
63
64#endif /* !defined (VBOX_WITH_XPCOM) */
65
66#include <VBox/com/defs.h>
67#include <VBox/com/assert.h>
68
69#define LOGREF(prefix, pObj, cRefs) com::LogRef("%s {%p} cRefs=%d\n", (prefix), (pObj), (cRefs))
70
71namespace com
72{
73 void LogRef(const char *pcszFormat, ...);
74}
75
76/**
77 * Returns @c true if two interface pointers are equal.
78 *
79 * According to the COM Identity Rule, interface pointers are considered to be
80 * equal if and only if IUnknown pointers queried on these interfaces pointers
81 * are equal (e.g. have the same binary value). Equal interface pointers
82 * represent the same object even if they are pointers to different interfaces.
83 *
84 * @param I1 Class of the first interface pointer (must be derived from
85 * IUnknown).
86 * @param I2 Class of the second interface pointer (must be derived from
87 * IUnknown).
88 */
89template <class I1, class I2>
90inline bool ComPtrEquals(I1 *aThis, I2 *aThat)
91{
92 IUnknown *thatUnk = NULL, *thisUnk = NULL;
93 if (aThat)
94 aThat->QueryInterface(COM_IIDOF(IUnknown), (void**)&thatUnk);
95 if (aThis)
96 aThis->QueryInterface(COM_IIDOF(IUnknown), (void**)&thisUnk);
97 bool equal = (thisUnk == thatUnk);
98 if (thisUnk)
99 thisUnk->Release();
100 if (thatUnk)
101 thatUnk->Release();
102 return equal;
103}
104
105/* specialization for <Any, IUnknown> */
106template <class I1>
107inline bool ComPtrEquals(I1 *aThis, IUnknown *aThat)
108{
109 IUnknown *thisUnk = NULL;
110 if (aThis)
111 aThis->QueryInterface(COM_IIDOF(IUnknown), (void**)&thisUnk);
112 bool equal = (thisUnk == aThat);
113 if (thisUnk)
114 thisUnk->Release();
115 return equal;
116}
117
118/** Specialization for <IUnknown, Any> */
119template <class I2>
120inline bool ComPtrEquals(IUnknown *aThis, I2 *aThat)
121{
122 IUnknown *thatUnk = NULL;
123 if (aThat)
124 aThat->QueryInterface(COM_IIDOF(IUnknown), (void**)&thatUnk);
125 bool equal = (aThis == thatUnk);
126 if (thatUnk)
127 thatUnk->Release();
128 return equal;
129}
130
131/* specialization for IUnknown */
132template<>
133inline bool ComPtrEquals<IUnknown, IUnknown>(IUnknown *aThis, IUnknown *aThat)
134{
135 return aThis == aThat;
136}
137
138/**
139 * Base template for smart COM pointers. Not intended to be used directly.
140 */
141template <class C>
142class ComPtrBase
143{
144public:
145
146 /* special template to disable AddRef()/Release() */
147 template <class I>
148 class NoAddRefRelease : public I
149 {
150 private:
151#if !defined (VBOX_WITH_XPCOM)
152 STDMETHOD_(ULONG, AddRef)() = 0;
153 STDMETHOD_(ULONG, Release)() = 0;
154#else /* !defined (VBOX_WITH_XPCOM) */
155 NS_IMETHOD_(nsrefcnt) AddRef(void) = 0;
156 NS_IMETHOD_(nsrefcnt) Release(void) = 0;
157#endif /* !defined (VBOX_WITH_XPCOM) */
158 };
159
160protected:
161
162 ComPtrBase()
163 : p(NULL)
164 {}
165
166 ComPtrBase(const ComPtrBase &that)
167 : p(that.p)
168 {
169 addref();
170 }
171
172 ComPtrBase(C *that_p)
173 : p(that_p)
174 {
175 addref();
176 }
177
178 ~ComPtrBase()
179 {
180 release();
181 }
182
183 ComPtrBase &operator=(const ComPtrBase &that)
184 {
185 safe_assign(that.p);
186 return *this;
187 }
188
189 ComPtrBase &operator=(C *that_p)
190 {
191 safe_assign(that_p);
192 return *this;
193 }
194
195public:
196
197 void setNull()
198 {
199 release();
200 p = NULL;
201 }
202
203 bool isNull() const
204 {
205 return (p == NULL);
206 }
207
208 bool operator!() const { return isNull(); }
209
210 bool operator<(C* that_p) const { return p < that_p; }
211 bool operator==(C* that_p) const { return p == that_p; }
212
213 template <class I>
214 bool equalsTo(I *aThat) const
215 {
216 return ComPtrEquals(p, aThat);
217 }
218
219 template <class OC>
220 bool equalsTo(const ComPtrBase <OC> &oc) const
221 {
222 return equalsTo((OC*)oc);
223 }
224
225 /** Intended to pass instances as in parameters to interface methods */
226 operator C*() const { return p; }
227
228 /**
229 * Dereferences the instance (redirects the -> operator to the managed
230 * pointer).
231 */
232 NoAddRefRelease<C>* operator->() const
233 {
234 AssertMsg(p, ("Managed pointer must not be null\n"));
235 return (NoAddRefRelease<C>*)p;
236 }
237
238 template <class I>
239 HRESULT queryInterfaceTo(I **pp) const
240 {
241 if (pp)
242 {
243 if (p)
244 {
245 return p->QueryInterface(COM_IIDOF(I), (void**)pp);
246 }
247 else
248 {
249 *pp = NULL;
250 return S_OK;
251 }
252 }
253
254 return E_INVALIDARG;
255 }
256
257 /** Intended to pass instances as out parameters to interface methods */
258 C **asOutParam()
259 {
260 setNull();
261 return &p;
262 }
263
264private:
265
266 void addref()
267 {
268 if (p)
269 p->AddRef();
270 }
271
272 void release()
273 {
274 if (p)
275 p->Release();
276 }
277
278 void safe_assign (C *that_p)
279 {
280 /* be aware of self-assignment */
281 if (that_p)
282 that_p->AddRef();
283 release();
284 p = that_p;
285 }
286
287 C *p;
288};
289
290/**
291 * Smart COM pointer wrapper that automatically manages refcounting of
292 * interface pointers.
293 *
294 * @param I COM interface class
295 */
296template <class I>
297class ComPtr : public ComPtrBase<I>
298{
299 typedef ComPtrBase<I> Base;
300
301public:
302
303 ComPtr() : Base() {}
304 ComPtr(const ComPtr &that) : Base(that) {}
305 ComPtr& operator=(const ComPtr &that)
306 {
307 Base::operator= (that);
308 return *this;
309 }
310
311 template <class OI>
312 ComPtr(OI *that_p) : Base() { operator=(that_p); }
313
314 /* specialization for I */
315 ComPtr(I *that_p) : Base(that_p) {}
316
317 template <class OC>
318 ComPtr(const ComPtr<OC> &oc) : Base() { operator=((OC*)oc); }
319
320 template <class OI>
321 ComPtr &operator=(OI *that_p)
322 {
323 if (that_p)
324 that_p->QueryInterface(COM_IIDOF(I), (void**)Base::asOutParam());
325 else
326 Base::setNull();
327 return *this;
328 }
329
330 /* specialization for I */
331 ComPtr &operator=(I *that_p)
332 {
333 Base::operator=(that_p);
334 return *this;
335 }
336
337 template <class OC>
338 ComPtr &operator=(const ComPtr<OC> &oc)
339 {
340 return operator=((OC*)oc);
341 }
342
343 /**
344 * Creates an in-process object of the given class ID and starts to
345 * manage a reference to the created object in case of success.
346 */
347 HRESULT createInprocObject (const CLSID &clsid)
348 {
349 HRESULT rc;
350 I *obj = NULL;
351#if !defined (VBOX_WITH_XPCOM)
352 rc = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, _ATL_IIDOF(I),
353 (void**)&obj);
354#else /* !defined (VBOX_WITH_XPCOM) */
355 nsCOMPtr<nsIComponentManager> manager;
356 rc = NS_GetComponentManager(getter_AddRefs(manager));
357 if (SUCCEEDED(rc))
358 rc = manager->CreateInstance(clsid, nsnull, NS_GET_IID(I),
359 (void **) &obj);
360#endif /* !defined (VBOX_WITH_XPCOM) */
361 *this = obj;
362 if (SUCCEEDED(rc))
363 obj->Release();
364 return rc;
365 }
366
367 /**
368 * Creates a local (out-of-process) object of the given class ID and starts
369 * to manage a reference to the created object in case of success.
370 *
371 * Note: In XPCOM, the out-of-process functionality is currently emulated
372 * through in-process wrapper objects (that start a dedicated process and
373 * redirect all object requests to that process). For this reason, this
374 * method is fully equivalent to #createInprocObject() for now.
375 */
376 HRESULT createLocalObject(const CLSID &clsid)
377 {
378#if !defined (VBOX_WITH_XPCOM)
379 HRESULT rc;
380 I *obj = NULL;
381 rc = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, _ATL_IIDOF(I),
382 (void**)&obj);
383 *this = obj;
384 if (SUCCEEDED(rc))
385 obj->Release();
386 return rc;
387#else /* !defined (VBOX_WITH_XPCOM) */
388 return createInprocObject(clsid);
389#endif /* !defined (VBOX_WITH_XPCOM) */
390 }
391
392#ifdef VBOX_WITH_XPCOM
393 /**
394 * Creates an object of the given class ID on the specified server and
395 * starts to manage a reference to the created object in case of success.
396 *
397 * @param serverName Name of the server to create an object within.
398 */
399 HRESULT createObjectOnServer(const CLSID &clsid, const char *serverName)
400 {
401 HRESULT rc;
402 I *obj = NULL;
403 nsCOMPtr<ipcIService> ipcServ = do_GetService(IPC_SERVICE_CONTRACTID, &rc);
404 if (SUCCEEDED(rc))
405 {
406 PRUint32 serverID = 0;
407 rc = ipcServ->ResolveClientName(serverName, &serverID);
408 if (SUCCEEDED (rc))
409 {
410 nsCOMPtr<ipcIDConnectService> dconServ = do_GetService(IPC_DCONNECTSERVICE_CONTRACTID, &rc);
411 if (SUCCEEDED(rc))
412 rc = dconServ->CreateInstance(serverID, clsid, NS_GET_IID(I),
413 (void**)&obj);
414 }
415 }
416 *this = obj;
417 if (SUCCEEDED(rc))
418 obj->Release();
419 return rc;
420 }
421#endif
422};
423
424/**
425 * Specialization of ComPtr<> for IUnknown to guarantee identity
426 * by always doing QueryInterface() when constructing or assigning from
427 * another interface pointer disregarding its type.
428 */
429template<>
430class ComPtr<IUnknown> : public ComPtrBase<IUnknown>
431{
432 typedef ComPtrBase<IUnknown> Base;
433
434public:
435
436 ComPtr() : Base() {}
437 ComPtr(const ComPtr &that) : Base (that) {}
438 ComPtr& operator=(const ComPtr &that)
439 {
440 Base::operator=(that);
441 return *this;
442 }
443
444 template <class OI>
445 ComPtr(OI *that_p) : Base() { operator=(that_p); }
446
447 template <class OC>
448 ComPtr(const ComPtr<OC> &oc) : Base() { operator=((OC*)oc); }
449
450 template <class OI>
451 ComPtr &operator=(OI *that_p)
452 {
453 if (that_p)
454 that_p->QueryInterface(COM_IIDOF(IUnknown), (void**)Base::asOutParam());
455 else
456 Base::setNull();
457 return *this;
458 }
459
460 template <class OC>
461 ComPtr &operator=(const ComPtr<OC> &oc)
462 {
463 return operator=((OC*)oc);
464 }
465};
466
467/**
468 * Smart COM pointer wrapper that automatically manages refcounting of
469 * pointers to interface implementation classes created on the component's
470 * (i.e. the server's) side. Differs from ComPtr by providing additional
471 * platform independent operations for creating new class instances.
472 *
473 * @param C class that implements some COM interface
474 */
475template <class C>
476class ComObjPtr : public ComPtrBase<C>
477{
478 typedef ComPtrBase<C> Base;
479
480public:
481
482 ComObjPtr() : Base() {}
483 ComObjPtr(const ComObjPtr &that) : Base(that) {}
484 ComObjPtr(C *that_p) : Base(that_p) {}
485
486 ComObjPtr& operator=(const ComObjPtr &that)
487 {
488 Base::operator=(that);
489 return *this;
490 }
491
492 ComObjPtr& operator=(C *that_p)
493 {
494 Base::operator=(that_p);
495 return *this;
496 }
497
498 /**
499 * Creates a new server-side object of the given component class and
500 * immediately starts to manage a pointer to the created object (the
501 * previous pointer, if any, is of course released when appropriate).
502 *
503 * @note This method should be used with care on weakly referenced
504 * smart pointers because it leaves the newly created object completely
505 * unreferenced (i.e., with reference count equal to zero),
506 *
507 * @note Win32: when VBOX_COM_OUTOFPROC_MODULE is defined, the created
508 * object doesn't increase the lock count of the server module, as it
509 * does otherwise.
510 */
511 HRESULT createObject()
512 {
513 HRESULT rc;
514#if !defined (VBOX_WITH_XPCOM)
515# ifdef VBOX_COM_OUTOFPROC_MODULE
516 CComObjectNoLock<C> *obj = new CComObjectNoLock<C>();
517 if (obj)
518 {
519 obj->InternalFinalConstructAddRef();
520 rc = obj->FinalConstruct();
521 obj->InternalFinalConstructRelease();
522 }
523 else
524 rc = E_OUTOFMEMORY;
525# else
526 CComObject<C> *obj = NULL;
527 rc = CComObject<C>::CreateInstance(&obj);
528# endif
529#else /* !defined (VBOX_WITH_XPCOM) */
530 CComObject<C> *obj = new CComObject<C>();
531 if (obj)
532 rc = obj->FinalConstruct();
533 else
534 rc = E_OUTOFMEMORY;
535#endif /* !defined (VBOX_WITH_XPCOM) */
536 *this = obj;
537 return rc;
538 }
539};
540#endif
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette