VirtualBox

source: vbox/trunk/src/VBox/Main/include/VirtualBoxBase.h@ 29945

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

compact headers

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 62.3 KB
Line 
1/** @file
2 * VirtualBox COM base classes definition
3 */
4
5/*
6 * Copyright (C) 2006-2010 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 */
16
17#ifndef ____H_VIRTUALBOXBASEIMPL
18#define ____H_VIRTUALBOXBASEIMPL
19
20#include <iprt/cdefs.h>
21#include <iprt/thread.h>
22
23#include <list>
24#include <map>
25
26#include "VBox/com/ErrorInfo.h"
27#include "VBox/com/SupportErrorInfo.h"
28#include "VBox/com/AutoLock.h"
29
30#include "VBox/com/VirtualBox.h"
31
32// avoid including VBox/settings.h and VBox/xml.h;
33// only declare the classes
34namespace xml
35{
36class File;
37}
38
39using namespace com;
40using namespace util;
41
42class AutoInitSpan;
43class AutoUninitSpan;
44
45class VirtualBox;
46class Machine;
47class Medium;
48class Host;
49typedef std::list< ComObjPtr<Medium> > MediaList;
50
51////////////////////////////////////////////////////////////////////////////////
52//
53// COM helpers
54//
55////////////////////////////////////////////////////////////////////////////////
56
57#if !defined (VBOX_WITH_XPCOM)
58
59#include <atlcom.h>
60
61/* use a special version of the singleton class factory,
62 * see KB811591 in msdn for more info. */
63
64#undef DECLARE_CLASSFACTORY_SINGLETON
65#define DECLARE_CLASSFACTORY_SINGLETON(obj) DECLARE_CLASSFACTORY_EX(CMyComClassFactorySingleton<obj>)
66
67template <class T>
68class CMyComClassFactorySingleton : public CComClassFactory
69{
70public:
71 CMyComClassFactorySingleton() : m_hrCreate(S_OK){}
72 virtual ~CMyComClassFactorySingleton(){}
73 // IClassFactory
74 STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj)
75 {
76 HRESULT hRes = E_POINTER;
77 if (ppvObj != NULL)
78 {
79 *ppvObj = NULL;
80 // Aggregation is not supported in singleton objects.
81 ATLASSERT(pUnkOuter == NULL);
82 if (pUnkOuter != NULL)
83 hRes = CLASS_E_NOAGGREGATION;
84 else
85 {
86 if (m_hrCreate == S_OK && m_spObj == NULL)
87 {
88 Lock();
89 __try
90 {
91 // Fix: The following If statement was moved inside the __try statement.
92 // Did another thread arrive here first?
93 if (m_hrCreate == S_OK && m_spObj == NULL)
94 {
95 // lock the module to indicate activity
96 // (necessary for the monitor shutdown thread to correctly
97 // terminate the module in case when CreateInstance() fails)
98 _pAtlModule->Lock();
99 CComObjectCached<T> *p;
100 m_hrCreate = CComObjectCached<T>::CreateInstance(&p);
101 if (SUCCEEDED(m_hrCreate))
102 {
103 m_hrCreate = p->QueryInterface(IID_IUnknown, (void**)&m_spObj);
104 if (FAILED(m_hrCreate))
105 {
106 delete p;
107 }
108 }
109 _pAtlModule->Unlock();
110 }
111 }
112 __finally
113 {
114 Unlock();
115 }
116 }
117 if (m_hrCreate == S_OK)
118 {
119 hRes = m_spObj->QueryInterface(riid, ppvObj);
120 }
121 else
122 {
123 hRes = m_hrCreate;
124 }
125 }
126 }
127 return hRes;
128 }
129 HRESULT m_hrCreate;
130 CComPtr<IUnknown> m_spObj;
131};
132
133#endif /* !defined (VBOX_WITH_XPCOM) */
134
135////////////////////////////////////////////////////////////////////////////////
136//
137// Macros
138//
139////////////////////////////////////////////////////////////////////////////////
140
141/**
142 * Special version of the Assert macro to be used within VirtualBoxBase
143 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
144 *
145 * In the debug build, this macro is equivalent to Assert.
146 * In the release build, this macro uses |setError(E_FAIL, ...)| to set the
147 * error info from the asserted expression.
148 *
149 * @see VirtualBoxSupportErrorInfoImpl::setError
150 *
151 * @param expr Expression which should be true.
152 */
153#if defined (DEBUG)
154#define ComAssert(expr) Assert(expr)
155#else
156#define ComAssert(expr) \
157 do { \
158 if (RT_UNLIKELY(!(expr))) \
159 setError(E_FAIL, "Assertion failed: [%s] at '%s' (%d) in %s.\n" \
160 "Please contact the product vendor!", \
161 #expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
162 } while (0)
163#endif
164
165/**
166 * Special version of the AssertMsg macro to be used within VirtualBoxBase
167 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
168 *
169 * See ComAssert for more info.
170 *
171 * @param expr Expression which should be true.
172 * @param a printf argument list (in parenthesis).
173 */
174#if defined (DEBUG)
175#define ComAssertMsg(expr, a) AssertMsg(expr, a)
176#else
177#define ComAssertMsg(expr, a) \
178 do { \
179 if (RT_UNLIKELY(!(expr))) \
180 setError(E_FAIL, "Assertion failed: [%s] at '%s' (%d) in %s.\n" \
181 "%s.\n" \
182 "Please contact the product vendor!", \
183 #expr, __FILE__, __LINE__, __PRETTY_FUNCTION__, Utf8StrFmt a .raw()); \
184 } while (0)
185#endif
186
187/**
188 * Special version of the AssertRC macro to be used within VirtualBoxBase
189 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
190 *
191 * See ComAssert for more info.
192 *
193 * @param vrc VBox status code.
194 */
195#if defined (DEBUG)
196#define ComAssertRC(vrc) AssertRC(vrc)
197#else
198#define ComAssertRC(vrc) ComAssertMsgRC(vrc, ("%Rra", vrc))
199#endif
200
201/**
202 * Special version of the AssertMsgRC macro to be used within VirtualBoxBase
203 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
204 *
205 * See ComAssert for more info.
206 *
207 * @param vrc VBox status code.
208 * @param msg printf argument list (in parenthesis).
209 */
210#if defined (DEBUG)
211#define ComAssertMsgRC(vrc, msg) AssertMsgRC(vrc, msg)
212#else
213#define ComAssertMsgRC(vrc, msg) ComAssertMsg(RT_SUCCESS(vrc), msg)
214#endif
215
216/**
217 * Special version of the AssertComRC macro to be used within VirtualBoxBase
218 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
219 *
220 * See ComAssert for more info.
221 *
222 * @param rc COM result code
223 */
224#if defined (DEBUG)
225#define ComAssertComRC(rc) AssertComRC(rc)
226#else
227#define ComAssertComRC(rc) ComAssertMsg(SUCCEEDED(rc), ("COM RC = %Rhrc (0x%08X)", (rc), (rc)))
228#endif
229
230
231/** Special version of ComAssert that returns ret if expr fails */
232#define ComAssertRet(expr, ret) \
233 do { ComAssert(expr); if (!(expr)) return (ret); } while (0)
234/** Special version of ComAssertMsg that returns ret if expr fails */
235#define ComAssertMsgRet(expr, a, ret) \
236 do { ComAssertMsg(expr, a); if (!(expr)) return (ret); } while (0)
237/** Special version of ComAssertRC that returns ret if vrc does not succeed */
238#define ComAssertRCRet(vrc, ret) \
239 do { ComAssertRC(vrc); if (!RT_SUCCESS(vrc)) return (ret); } while (0)
240/** Special version of ComAssertMsgRC that returns ret if vrc does not succeed */
241#define ComAssertMsgRCRet(vrc, msg, ret) \
242 do { ComAssertMsgRC(vrc, msg); if (!RT_SUCCESS(vrc)) return (ret); } while (0)
243/** Special version of ComAssertFailed that returns ret */
244#define ComAssertFailedRet(ret) \
245 do { ComAssertFailed(); return (ret); } while (0)
246/** Special version of ComAssertMsgFailed that returns ret */
247#define ComAssertMsgFailedRet(msg, ret) \
248 do { ComAssertMsgFailed(msg); return (ret); } while (0)
249/** Special version of ComAssertComRC that returns ret if rc does not succeed */
250#define ComAssertComRCRet(rc, ret) \
251 do { ComAssertComRC(rc); if (!SUCCEEDED(rc)) return (ret); } while (0)
252/** Special version of ComAssertComRC that returns rc if rc does not succeed */
253#define ComAssertComRCRetRC(rc) \
254 do { ComAssertComRC(rc); if (!SUCCEEDED(rc)) return (rc); } while (0)
255
256
257/** Special version of ComAssert that evaluates eval and breaks if expr fails */
258#define ComAssertBreak(expr, eval) \
259 if (1) { ComAssert(expr); if (!(expr)) { eval; break; } } else do {} while (0)
260/** Special version of ComAssertMsg that evaluates eval and breaks if expr fails */
261#define ComAssertMsgBreak(expr, a, eval) \
262 if (1) { ComAssertMsg(expr, a); if (!(expr)) { eval; break; } } else do {} while (0)
263/** Special version of ComAssertRC that evaluates eval and breaks if vrc does not succeed */
264#define ComAssertRCBreak(vrc, eval) \
265 if (1) { ComAssertRC(vrc); if (!RT_SUCCESS(vrc)) { eval; break; } } else do {} while (0)
266/** Special version of ComAssertMsgRC that evaluates eval and breaks if vrc does not succeed */
267#define ComAssertMsgRCBreak(vrc, msg, eval) \
268 if (1) { ComAssertMsgRC(vrc, msg); if (!RT_SUCCESS(vrc)) { eval; break; } } else do {} while (0)
269/** Special version of ComAssertFailed that evaluates eval and breaks */
270#define ComAssertFailedBreak(eval) \
271 if (1) { ComAssertFailed(); { eval; break; } } else do {} while (0)
272/** Special version of ComAssertMsgFailed that evaluates eval and breaks */
273#define ComAssertMsgFailedBreak(msg, eval) \
274 if (1) { ComAssertMsgFailed (msg); { eval; break; } } else do {} while (0)
275/** Special version of ComAssertComRC that evaluates eval and breaks if rc does not succeed */
276#define ComAssertComRCBreak(rc, eval) \
277 if (1) { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { eval; break; } } else do {} while (0)
278/** Special version of ComAssertComRC that just breaks if rc does not succeed */
279#define ComAssertComRCBreakRC(rc) \
280 if (1) { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { break; } } else do {} while (0)
281
282
283/** Special version of ComAssert that evaluates eval and throws it if expr fails */
284#define ComAssertThrow(expr, eval) \
285 if (1) { ComAssert(expr); if (!(expr)) { throw (eval); } } else do {} while (0)
286/** Special version of ComAssertMsg that evaluates eval and throws it if expr fails */
287#define ComAssertMsgThrow(expr, a, eval) \
288 if (1) { ComAssertMsg(expr, a); if (!(expr)) { throw (eval); } } else do {} while (0)
289/** Special version of ComAssertRC that evaluates eval and throws it if vrc does not succeed */
290#define ComAssertRCThrow(vrc, eval) \
291 if (1) { ComAssertRC(vrc); if (!RT_SUCCESS(vrc)) { throw (eval); } } else do {} while (0)
292/** Special version of ComAssertMsgRC that evaluates eval and throws it if vrc does not succeed */
293#define ComAssertMsgRCThrow(vrc, msg, eval) \
294 if (1) { ComAssertMsgRC(vrc, msg); if (!RT_SUCCESS(vrc)) { throw (eval); } } else do {} while (0)
295/** Special version of ComAssertFailed that evaluates eval and throws it */
296#define ComAssertFailedThrow(eval) \
297 if (1) { ComAssertFailed(); { throw (eval); } } else do {} while (0)
298/** Special version of ComAssertMsgFailed that evaluates eval and throws it */
299#define ComAssertMsgFailedThrow(msg, eval) \
300 if (1) { ComAssertMsgFailed (msg); { throw (eval); } } else do {} while (0)
301/** Special version of ComAssertComRC that evaluates eval and throws it if rc does not succeed */
302#define ComAssertComRCThrow(rc, eval) \
303 if (1) { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { throw (eval); } } else do {} while (0)
304/** Special version of ComAssertComRC that just throws rc if rc does not succeed */
305#define ComAssertComRCThrowRC(rc) \
306 if (1) { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { throw rc; } } else do {} while (0)
307
308////////////////////////////////////////////////////////////////////////////////
309
310/**
311 * Checks that the pointer argument is not NULL and returns E_INVALIDARG +
312 * extended error info on failure.
313 * @param arg Input pointer-type argument (strings, interface pointers...)
314 */
315#define CheckComArgNotNull(arg) \
316 do { \
317 if (RT_UNLIKELY((arg) == NULL)) \
318 return setError(E_INVALIDARG, tr("Argument %s is NULL"), #arg); \
319 } while (0)
320
321/**
322 * Checks that safe array argument is not NULL and returns E_INVALIDARG +
323 * extended error info on failure.
324 * @param arg Input safe array argument (strings, interface pointers...)
325 */
326#define CheckComArgSafeArrayNotNull(arg) \
327 do { \
328 if (RT_UNLIKELY(ComSafeArrayInIsNull(arg))) \
329 return setError(E_INVALIDARG, tr("Argument %s is NULL"), #arg); \
330 } while (0)
331
332/**
333 * Checks that the string argument is not a NULL or empty string and returns
334 * E_INVALIDARG + extended error info on failure.
335 * @param arg Input string argument (BSTR etc.).
336 */
337#define CheckComArgStrNotEmptyOrNull(arg) \
338 do { \
339 if (RT_UNLIKELY((arg) == NULL || *(arg) == '\0')) \
340 return setError(E_INVALIDARG, \
341 tr("Argument %s is empty or NULL"), #arg); \
342 } while (0)
343
344/**
345 * Checks that the given expression (that must involve the argument) is true and
346 * returns E_INVALIDARG + extended error info on failure.
347 * @param arg Argument.
348 * @param expr Expression to evaluate.
349 */
350#define CheckComArgExpr(arg, expr) \
351 do { \
352 if (RT_UNLIKELY(!(expr))) \
353 return setError(E_INVALIDARG, \
354 tr("Argument %s is invalid (must be %s)"), #arg, #expr); \
355 } while (0)
356
357/**
358 * Checks that the given expression (that must involve the argument) is true and
359 * returns E_INVALIDARG + extended error info on failure. The error message must
360 * be customized.
361 * @param arg Argument.
362 * @param expr Expression to evaluate.
363 * @param msg Parenthesized printf-like expression (must start with a verb,
364 * like "must be one of...", "is not within...").
365 */
366#define CheckComArgExprMsg(arg, expr, msg) \
367 do { \
368 if (RT_UNLIKELY(!(expr))) \
369 return setError(E_INVALIDARG, tr ("Argument %s %s"), \
370 #arg, Utf8StrFmt msg .raw()); \
371 } while (0)
372
373/**
374 * Checks that the given pointer to an output argument is valid and returns
375 * E_POINTER + extended error info otherwise.
376 * @param arg Pointer argument.
377 */
378#define CheckComArgOutPointerValid(arg) \
379 do { \
380 if (RT_UNLIKELY(!VALID_PTR(arg))) \
381 return setError(E_POINTER, \
382 tr("Output argument %s points to invalid memory location (%p)"), \
383 #arg, (void *) (arg)); \
384 } while (0)
385
386/**
387 * Checks that the given pointer to an output safe array argument is valid and
388 * returns E_POINTER + extended error info otherwise.
389 * @param arg Safe array argument.
390 */
391#define CheckComArgOutSafeArrayPointerValid(arg) \
392 do { \
393 if (RT_UNLIKELY(ComSafeArrayOutIsNull(arg))) \
394 return setError(E_POINTER, \
395 tr("Output argument %s points to invalid memory location (%p)"), \
396 #arg, (void *) (arg)); \
397 } while (0)
398
399/**
400 * Sets the extended error info and returns E_NOTIMPL.
401 */
402#define ReturnComNotImplemented() \
403 do { \
404 return setError(E_NOTIMPL, tr("Method %s is not implemented"), __FUNCTION__); \
405 } while (0)
406
407/**
408 * Declares an empty constructor and destructor for the given class.
409 * This is useful to prevent the compiler from generating the default
410 * ctor and dtor, which in turn allows to use forward class statements
411 * (instead of including their header files) when declaring data members of
412 * non-fundamental types with constructors (which are always called implicitly
413 * by constructors and by the destructor of the class).
414 *
415 * This macro is to be placed within (the public section of) the class
416 * declaration. Its counterpart, DEFINE_EMPTY_CTOR_DTOR, must be placed
417 * somewhere in one of the translation units (usually .cpp source files).
418 *
419 * @param cls class to declare a ctor and dtor for
420 */
421#define DECLARE_EMPTY_CTOR_DTOR(cls) cls(); ~cls();
422
423/**
424 * Defines an empty constructor and destructor for the given class.
425 * See DECLARE_EMPTY_CTOR_DTOR for more info.
426 */
427#define DEFINE_EMPTY_CTOR_DTOR(cls) \
428 cls::cls() { /*empty*/ } \
429 cls::~cls() { /*empty*/ }
430
431////////////////////////////////////////////////////////////////////////////////
432//
433// VirtualBoxBase
434//
435////////////////////////////////////////////////////////////////////////////////
436
437/**
438 * This enum is used in the virtual method VirtualBoxBasePro::getClassID() to
439 * allow VirtualBox classes to identify themselves. Subclasses can override
440 * that method and return a value from this enum if run-time identification is
441 * needed anywhere.
442 */
443enum VBoxClsID
444{
445 clsidVirtualBox,
446 clsidHost,
447 clsidMachine,
448 clsidSessionMachine,
449 clsidSnapshotMachine,
450 clsidSnapshot,
451 clsidOther
452};
453
454/**
455 * Abstract base class for all component classes implementing COM
456 * interfaces of the VirtualBox COM library.
457 *
458 * Declares functionality that should be available in all components.
459 *
460 * Note that this class is always subclassed using the virtual keyword so
461 * that only one instance of its VTBL and data is present in each derived class
462 * even in case if VirtualBoxBaseProto appears more than once among base classes
463 * of the particular component as a result of multiple inheritance.
464 *
465 * This makes it possible to have intermediate base classes used by several
466 * components that implement some common interface functionality but still let
467 * the final component classes choose what VirtualBoxBase variant it wants to
468 * use.
469 *
470 * Among the basic functionality implemented by this class is the primary object
471 * state that indicates if the object is ready to serve the calls, and if not,
472 * what stage it is currently at. Here is the primary state diagram:
473 *
474 * +-------------------------------------------------------+
475 * | |
476 * | (InitFailed) -----------------------+ |
477 * | ^ | |
478 * v | v |
479 * [*] ---> NotReady ----> (InInit) -----> Ready -----> (InUninit) ----+
480 * ^ |
481 * | v
482 * | Limited
483 * | |
484 * +-------+
485 *
486 * The object is fully operational only when its state is Ready. The Limited
487 * state means that only some vital part of the object is operational, and it
488 * requires some sort of reinitialization to become fully operational. The
489 * NotReady state means the object is basically dead: it either was not yet
490 * initialized after creation at all, or was uninitialized and is waiting to be
491 * destroyed when the last reference to it is released. All other states are
492 * transitional.
493 *
494 * The NotReady->InInit->Ready, NotReady->InInit->Limited and
495 * NotReady->InInit->InitFailed transition is done by the AutoInitSpan smart
496 * class.
497 *
498 * The Limited->InInit->Ready, Limited->InInit->Limited and
499 * Limited->InInit->InitFailed transition is done by the AutoReinitSpan smart
500 * class.
501 *
502 * The Ready->InUninit->NotReady and InitFailed->InUninit->NotReady
503 * transitions are done by the AutoUninitSpan smart class.
504 *
505 * In order to maintain the primary state integrity and declared functionality
506 * all subclasses must:
507 *
508 * 1) Use the above Auto*Span classes to perform state transitions. See the
509 * individual class descriptions for details.
510 *
511 * 2) All public methods of subclasses (i.e. all methods that can be called
512 * directly, not only from within other methods of the subclass) must have a
513 * standard prolog as described in the AutoCaller and AutoLimitedCaller
514 * documentation. Alternatively, they must use addCaller()/releaseCaller()
515 * directly (and therefore have both the prolog and the epilog), but this is
516 * not recommended.
517 */
518class ATL_NO_VTABLE VirtualBoxBase
519 : public Lockable,
520 public CComObjectRootEx<CComMultiThreadModel>
521{
522public:
523 enum State { NotReady, Ready, InInit, InUninit, InitFailed, Limited };
524
525 VirtualBoxBase();
526 virtual ~VirtualBoxBase();
527
528 static const char *translate(const char *context, const char *sourceText,
529 const char *comment = 0);
530
531public:
532
533 /**
534 * Unintialization method.
535 *
536 * Must be called by all final implementations (component classes) when the
537 * last reference to the object is released, before calling the destructor.
538 *
539 * This method is also automatically called by the uninit() method of this
540 * object's parent if this object is a dependent child of a class derived
541 * from VirtualBoxBaseWithChildren (see
542 * VirtualBoxBaseWithChildren::addDependentChild).
543 *
544 * @note Never call this method the AutoCaller scope or after the
545 * #addCaller() call not paired by #releaseCaller() because it is a
546 * guaranteed deadlock. See AutoUninitSpan for details.
547 */
548 virtual void uninit() {}
549
550 virtual HRESULT addCaller(State *aState = NULL, bool aLimited = false);
551 virtual void releaseCaller();
552
553 /**
554 * Adds a limited caller. This method is equivalent to doing
555 * <tt>addCaller (aState, true)</tt>, but it is preferred because provides
556 * better self-descriptiveness. See #addCaller() for more info.
557 */
558 HRESULT addLimitedCaller(State *aState = NULL)
559 {
560 return addCaller(aState, true /* aLimited */);
561 }
562
563 /**
564 * Simple run-time type identification without having to enable C++ RTTI.
565 * The class IDs are defined in VirtualBoxBase.h.
566 * @return
567 */
568 virtual VBoxClsID getClassID() const
569 {
570 return clsidOther;
571 }
572
573 /**
574 * Override of the default locking class to be used for validating lock
575 * order with the standard member lock handle.
576 */
577 virtual VBoxLockingClass getLockingClass() const
578 {
579 return LOCKCLASS_OTHEROBJECT;
580 }
581
582 virtual RWLockHandle *lockHandle() const;
583
584 /**
585 * Returns a lock handle used to protect the primary state fields (used by
586 * #addCaller(), AutoInitSpan, AutoUninitSpan, etc.). Only intended to be
587 * used for similar purposes in subclasses. WARNING: NO any other locks may
588 * be requested while holding this lock!
589 */
590 WriteLockHandle *stateLockHandle() { return &mStateLock; }
591
592private:
593
594 void setState(State aState)
595 {
596 Assert(mState != aState);
597 mState = aState;
598 mStateChangeThread = RTThreadSelf();
599 }
600
601 /** Primary state of this object */
602 State mState;
603 /** Thread that caused the last state change */
604 RTTHREAD mStateChangeThread;
605 /** Total number of active calls to this object */
606 unsigned mCallers;
607 /** Posted when the number of callers drops to zero */
608 RTSEMEVENT mZeroCallersSem;
609 /** Posted when the object goes from InInit/InUninit to some other state */
610 RTSEMEVENTMULTI mInitUninitSem;
611 /** Number of threads waiting for mInitUninitDoneSem */
612 unsigned mInitUninitWaiters;
613
614 /** Protects access to state related data members */
615 WriteLockHandle mStateLock;
616
617 /** User-level object lock for subclasses */
618 mutable RWLockHandle *mObjectLock;
619
620 friend class AutoInitSpan;
621 friend class AutoReinitSpan;
622 friend class AutoUninitSpan;
623};
624
625////////////////////////////////////////////////////////////////////////////////
626//
627// VirtualBoxSupportTranslation, VirtualBoxSupportErrorInfoImpl
628//
629////////////////////////////////////////////////////////////////////////////////
630
631/**
632 * This macro adds the error info support to methods of the VirtualBoxBase
633 * class (by overriding them). Place it to the public section of the
634 * VirtualBoxBase subclass and the following methods will set the extended
635 * error info in case of failure instead of just returning the result code:
636 *
637 * <ul>
638 * <li>VirtualBoxBase::addCaller()
639 * </ul>
640 *
641 * @note The given VirtualBoxBase subclass must also inherit from both
642 * VirtualBoxSupportErrorInfoImpl and VirtualBoxSupportTranslation templates!
643 *
644 * @param C VirtualBoxBase subclass to add the error info support to
645 */
646#define VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(C) \
647 virtual HRESULT addCaller(VirtualBoxBase::State *aState = NULL, \
648 bool aLimited = false) \
649 { \
650 VirtualBoxBase::State protoState; \
651 HRESULT rc = VirtualBoxBase::addCaller(&protoState, aLimited); \
652 if (FAILED(rc)) \
653 { \
654 if (protoState == VirtualBoxBase::Limited) \
655 rc = setError(rc, tr("The object functionality is limited")); \
656 else \
657 rc = setError(rc, tr("The object is not ready")); \
658 } \
659 if (aState) \
660 *aState = protoState; \
661 return rc; \
662 } \
663
664////////////////////////////////////////////////////////////////////////////////
665
666/** Helper for VirtualBoxSupportTranslation. */
667class VirtualBoxSupportTranslationBase
668{
669protected:
670 static bool cutClassNameFrom__PRETTY_FUNCTION__(char *aPrettyFunctionName);
671};
672
673/**
674 * The VirtualBoxSupportTranslation template implements the NLS string
675 * translation support for the given class.
676 *
677 * Translation support is provided by the static #tr() function. This function,
678 * given a string in UTF-8 encoding, looks up for a translation of the given
679 * string by calling the VirtualBoxBase::translate() global function which
680 * receives the name of the enclosing class ("context of translation") as the
681 * additional argument and returns a translated string based on the currently
682 * active language.
683 *
684 * @param C Class that needs to support the string translation.
685 *
686 * @note Every class that wants to use the #tr() function in its own methods
687 * must inherit from this template, regardless of whether its base class
688 * (if any) inherits from it or not. Otherwise, the translation service
689 * will not work correctly. However, the declaration of the derived
690 * class must contain
691 * the <tt>COM_SUPPORTTRANSLATION_OVERRIDE (<ClassName>)</tt> macro if one
692 * of its base classes also inherits from this template (to resolve the
693 * ambiguity of the #tr() function).
694 */
695template<class C>
696class VirtualBoxSupportTranslation : virtual protected VirtualBoxSupportTranslationBase
697{
698public:
699
700 /**
701 * Translates the given text string by calling VirtualBoxBase::translate()
702 * and passing the name of the C class as the first argument ("context of
703 * translation") See VirtualBoxBase::translate() for more info.
704 *
705 * @param aSourceText String to translate.
706 * @param aComment Comment to the string to resolve possible
707 * ambiguities (NULL means no comment).
708 *
709 * @return Translated version of the source string in UTF-8 encoding, or
710 * the source string itself if the translation is not found in the
711 * specified context.
712 */
713 inline static const char *tr(const char *aSourceText,
714 const char *aComment = NULL)
715 {
716 return VirtualBoxBase::translate(className(), aSourceText, aComment);
717 }
718
719protected:
720
721 static const char *className()
722 {
723 static char fn[sizeof(__PRETTY_FUNCTION__) + 1];
724 if (!sClassName)
725 {
726 strcpy(fn, __PRETTY_FUNCTION__);
727 cutClassNameFrom__PRETTY_FUNCTION__(fn);
728 sClassName = fn;
729 }
730 return sClassName;
731 }
732
733private:
734
735 static const char *sClassName;
736};
737
738template<class C>
739const char *VirtualBoxSupportTranslation<C>::sClassName = NULL;
740
741/**
742 * This macro must be invoked inside the public section of the declaration of
743 * the class inherited from the VirtualBoxSupportTranslation template in case
744 * if one of its other base classes also inherits from that template. This is
745 * necessary to resolve the ambiguity of the #tr() function.
746 *
747 * @param C Class that inherits the VirtualBoxSupportTranslation template
748 * more than once (through its other base clases).
749 */
750#define VIRTUALBOXSUPPORTTRANSLATION_OVERRIDE(C) \
751 inline static const char *tr(const char *aSourceText, \
752 const char *aComment = NULL) \
753 { \
754 return VirtualBoxSupportTranslation<C>::tr(aSourceText, aComment); \
755 }
756
757/**
758 * Dummy macro that is used to shut down Qt's lupdate tool warnings in some
759 * situations. This macro needs to be present inside (better at the very
760 * beginning) of the declaration of the class that inherits from
761 * VirtualBoxSupportTranslation template, to make lupdate happy.
762 */
763#define Q_OBJECT
764
765////////////////////////////////////////////////////////////////////////////////
766
767/**
768 * Helper for the VirtualBoxSupportErrorInfoImpl template.
769 */
770/// @todo switch to com::SupportErrorInfo* and remove
771class VirtualBoxSupportErrorInfoImplBase
772{
773 static HRESULT setErrorInternal(HRESULT aResultCode,
774 const GUID &aIID,
775 const wchar_t *aComponent,
776 const Bstr &aText,
777 bool aWarning,
778 bool aLogIt);
779
780protected:
781
782 /**
783 * The MultiResult class is a com::FWResult enhancement that also acts as a
784 * switch to turn on multi-error mode for #setError() or #setWarning()
785 * calls.
786 *
787 * When an instance of this class is created, multi-error mode is turned on
788 * for the current thread and the turn-on counter is increased by one. In
789 * multi-error mode, a call to #setError() or #setWarning() does not
790 * overwrite the current error or warning info object possibly set on the
791 * current thread by other method calls, but instead it stores this old
792 * object in the IVirtualBoxErrorInfo::next attribute of the new error
793 * object being set.
794 *
795 * This way, error/warning objects are stacked together and form a chain of
796 * errors where the most recent error is the first one retrieved by the
797 * calling party, the preceding error is what the
798 * IVirtualBoxErrorInfo::next attribute of the first error points to, and so
799 * on, up to the first error or warning occurred which is the last in the
800 * chain. See IVirtualBoxErrorInfo documentation for more info.
801 *
802 * When the instance of the MultiResult class goes out of scope and gets
803 * destroyed, it automatically decreases the turn-on counter by one. If
804 * the counter drops to zero, multi-error mode for the current thread is
805 * turned off and the thread switches back to single-error mode where every
806 * next error or warning object overwrites the previous one.
807 *
808 * Note that the caller of a COM method uses a non-S_OK result code to
809 * decide if the method has returned an error (negative codes) or a warning
810 * (positive non-zero codes) and will query extended error info only in
811 * these two cases. However, since multi-error mode implies that the method
812 * doesn't return control return to the caller immediately after the first
813 * error or warning but continues its execution, the functionality provided
814 * by the base com::FWResult class becomes very useful because it allows to
815 * preserve the error or the warning result code even if it is later assigned
816 * a S_OK value multiple times. See com::FWResult for details.
817 *
818 * Here is the typical usage pattern:
819 * <code>
820
821 HRESULT Bar::method()
822 {
823 // assume multi-errors are turned off here...
824
825 if (something)
826 {
827 // Turn on multi-error mode and make sure severity is preserved
828 MultiResult rc = foo->method1();
829
830 // return on fatal error, but continue on warning or on success
831 if (FAILED(rc)) return rc;
832
833 rc = foo->method2();
834 // no matter what result, stack it and continue
835
836 // ...
837
838 // return the last worst result code (it will be preserved even if
839 // foo->method2() returns S_OK.
840 return rc;
841 }
842
843 // multi-errors are turned off here again...
844
845 return S_OK;
846 }
847
848 * </code>
849 *
850 *
851 * @note This class is intended to be instantiated on the stack, therefore
852 * You cannot create them using new(). Although it is possible to copy
853 * instances of MultiResult or return them by value, please never do
854 * that as it is breaks the class semantics (and will assert).
855 */
856 class MultiResult : public com::FWResult
857 {
858 public:
859
860 /**
861 * @copydoc com::FWResult::FWResult().
862 */
863 MultiResult(HRESULT aRC = E_FAIL) : FWResult(aRC) { init(); }
864
865 MultiResult(const MultiResult &aThat) : FWResult(aThat)
866 {
867 /* We need this copy constructor only for GCC that wants to have
868 * it in case of expressions like |MultiResult rc = E_FAIL;|. But
869 * we assert since the optimizer should actually avoid the
870 * temporary and call the other constructor directly instead. */
871 AssertFailed();
872 init();
873 }
874
875 ~MultiResult();
876
877 MultiResult &operator=(HRESULT aRC)
878 {
879 com::FWResult::operator=(aRC);
880 return *this;
881 }
882
883 MultiResult &operator=(const MultiResult &aThat)
884 {
885 /* We need this copy constructor only for GCC that wants to have
886 * it in case of expressions like |MultiResult rc = E_FAIL;|. But
887 * we assert since the optimizer should actually avoid the
888 * temporary and call the other constructor directly instead. */
889 AssertFailed();
890 com::FWResult::operator=(aThat);
891 return *this;
892 }
893
894 private:
895
896 DECLARE_CLS_NEW_DELETE_NOOP(MultiResult)
897
898 void init();
899
900 static RTTLS sCounter;
901
902 friend class VirtualBoxSupportErrorInfoImplBase;
903 };
904
905 static HRESULT setError(HRESULT aResultCode,
906 const GUID &aIID,
907 const wchar_t *aComponent,
908 const Bstr &aText,
909 bool aLogIt = true)
910 {
911 return setErrorInternal(aResultCode, aIID, aComponent, aText,
912 false /* aWarning */, aLogIt);
913 }
914
915 static HRESULT setWarning(HRESULT aResultCode,
916 const GUID &aIID,
917 const wchar_t *aComponent,
918 const Bstr &aText)
919 {
920 return setErrorInternal(aResultCode, aIID, aComponent, aText,
921 true /* aWarning */, true /* aLogIt */);
922 }
923
924 static HRESULT setError(HRESULT aResultCode,
925 const GUID &aIID,
926 const wchar_t *aComponent,
927 const char *aText, va_list aArgs, bool aLogIt = true)
928 {
929 return setErrorInternal(aResultCode, aIID, aComponent,
930 Utf8StrFmtVA (aText, aArgs),
931 false /* aWarning */, aLogIt);
932 }
933
934 static HRESULT setWarning(HRESULT aResultCode,
935 const GUID &aIID,
936 const wchar_t *aComponent,
937 const char *aText, va_list aArgs)
938 {
939 return setErrorInternal(aResultCode, aIID, aComponent,
940 Utf8StrFmtVA (aText, aArgs),
941 true /* aWarning */, true /* aLogIt */);
942 }
943};
944
945/**
946 * This template implements ISupportErrorInfo for the given component class
947 * and provides the #setError() method to conveniently set the error information
948 * from within interface methods' implementations.
949 *
950 * On Windows, the template argument must define a COM interface map using
951 * BEGIN_COM_MAP / END_COM_MAP macros and this map must contain a
952 * COM_INTERFACE_ENTRY(ISupportErrorInfo) definition. All interface entries
953 * that follow it will be considered to support IErrorInfo, i.e. the
954 * InterfaceSupportsErrorInfo() implementation will return S_OK for the
955 * corresponding IID.
956 *
957 * On all platforms, the template argument must also define the following
958 * method: |public static const wchar_t *C::getComponentName()|. See
959 * #setError(HRESULT, const char *, ...) for a description on how it is
960 * used.
961 *
962 * @param C
963 * component class that implements one or more COM interfaces
964 * @param I
965 * default interface for the component. This interface's IID is used
966 * by the shortest form of #setError, for convenience.
967 */
968/// @todo switch to com::SupportErrorInfo* and remove
969template<class C, class I>
970class ATL_NO_VTABLE VirtualBoxSupportErrorInfoImpl
971 : protected VirtualBoxSupportErrorInfoImplBase
972#if !defined (VBOX_WITH_XPCOM)
973 , public ISupportErrorInfo
974#else
975#endif
976{
977public:
978
979#if !defined (VBOX_WITH_XPCOM)
980 STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid)
981 {
982 const _ATL_INTMAP_ENTRY* pEntries = C::_GetEntries();
983 Assert(pEntries);
984 if (!pEntries)
985 return S_FALSE;
986
987 BOOL bSupports = FALSE;
988 BOOL bISupportErrorInfoFound = FALSE;
989
990 while (pEntries->pFunc != NULL && !bSupports)
991 {
992 if (!bISupportErrorInfoFound)
993 {
994 // skip the com map entries until ISupportErrorInfo is found
995 bISupportErrorInfoFound =
996 InlineIsEqualGUID(*(pEntries->piid), IID_ISupportErrorInfo);
997 }
998 else
999 {
1000 // look for the requested interface in the rest of the com map
1001 bSupports = InlineIsEqualGUID(*(pEntries->piid), riid);
1002 }
1003 pEntries++;
1004 }
1005
1006 Assert(bISupportErrorInfoFound);
1007
1008 return bSupports ? S_OK : S_FALSE;
1009 }
1010#endif // !defined (VBOX_WITH_XPCOM)
1011
1012protected:
1013
1014 /**
1015 * Sets the error information for the current thread.
1016 * This information can be retrieved by a caller of an interface method
1017 * using IErrorInfo on Windows or nsIException on Linux, or the cross-platform
1018 * IVirtualBoxErrorInfo interface that provides extended error info (only
1019 * for components from the VirtualBox COM library). Alternatively, the
1020 * platform-independent class com::ErrorInfo (defined in VBox[XP]COM.lib)
1021 * can be used to retrieve error info in a convenient way.
1022 *
1023 * It is assumed that the interface method that uses this function returns
1024 * an unsuccessful result code to the caller (otherwise, there is no reason
1025 * for the caller to try to retrieve error info after method invocation).
1026 *
1027 * Here is a table of correspondence between this method's arguments
1028 * and IErrorInfo/nsIException/IVirtualBoxErrorInfo attributes/methods:
1029 *
1030 * argument IErrorInfo nsIException IVirtualBoxErrorInfo
1031 * ----------------------------------------------------------------
1032 * resultCode -- result resultCode
1033 * iid GetGUID -- interfaceID
1034 * component GetSource -- component
1035 * text GetDescription message text
1036 *
1037 * This method is rarely needs to be used though. There are more convenient
1038 * overloaded versions, that automatically substitute some arguments
1039 * taking their values from the template parameters. See
1040 * #setError(HRESULT, const char *, ...) for an example.
1041 *
1042 * @param aResultCode result (error) code, must not be S_OK
1043 * @param aIID IID of the interface that defines the error
1044 * @param aComponent name of the component that generates the error
1045 * @param aText error message (must not be null), an RTStrPrintf-like
1046 * format string in UTF-8 encoding
1047 * @param ... list of arguments for the format string
1048 *
1049 * @return
1050 * the error argument, for convenience, If an error occurs while
1051 * creating error info itself, that error is returned instead of the
1052 * error argument.
1053 */
1054 static HRESULT setError(HRESULT aResultCode, const GUID &aIID,
1055 const wchar_t *aComponent,
1056 const char *aText, ...)
1057 {
1058 va_list args;
1059 va_start(args, aText);
1060 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError(aResultCode,
1061 aIID,
1062 aComponent,
1063 aText,
1064 args,
1065 true /* aLogIt */);
1066 va_end(args);
1067 return rc;
1068 }
1069
1070 /**
1071 * This method is the same as #setError() except that it makes sure @a
1072 * aResultCode doesn't have the error severity bit (31) set when passed
1073 * down to the created IVirtualBoxErrorInfo object.
1074 *
1075 * The error severity bit is always cleared by this call, thereof you can
1076 * use ordinary E_XXX result code constants, for convenience. However, this
1077 * behavior may be non-standard on some COM platforms.
1078 */
1079 static HRESULT setWarning(HRESULT aResultCode, const GUID &aIID,
1080 const wchar_t *aComponent,
1081 const char *aText, ...)
1082 {
1083 va_list args;
1084 va_start(args, aText);
1085 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setWarning(
1086 aResultCode, aIID, aComponent, aText, args);
1087 va_end(args);
1088 return rc;
1089 }
1090
1091 /**
1092 * Sets the error information for the current thread.
1093 * A convenience method that automatically sets the default interface
1094 * ID (taken from the I template argument) and the component name
1095 * (a value of C::getComponentName()).
1096 *
1097 * See #setError(HRESULT, const GUID &, const wchar_t *, const char *text, ...)
1098 * for details.
1099 *
1100 * This method is the most common (and convenient) way to set error
1101 * information from within interface methods. A typical pattern of usage
1102 * is looks like this:
1103 *
1104 * <code>
1105 * return setError(E_FAIL, "Terrible Error");
1106 * </code>
1107 * or
1108 * <code>
1109 * HRESULT rc = setError(E_FAIL, "Terrible Error");
1110 * ...
1111 * return rc;
1112 * </code>
1113 */
1114 static HRESULT setError(HRESULT aResultCode, const char *aText, ...)
1115 {
1116 va_list args;
1117 va_start(args, aText);
1118 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError(aResultCode,
1119 COM_IIDOF(I),
1120 C::getComponentName(),
1121 aText,
1122 args,
1123 true /* aLogIt */);
1124 va_end(args);
1125 return rc;
1126 }
1127
1128 /**
1129 * This method is the same as #setError() except that it makes sure @a
1130 * aResultCode doesn't have the error severity bit (31) set when passed
1131 * down to the created IVirtualBoxErrorInfo object.
1132 *
1133 * The error severity bit is always cleared by this call, thereof you can
1134 * use ordinary E_XXX result code constants, for convenience. However, this
1135 * behavior may be non-standard on some COM platforms.
1136 */
1137 static HRESULT setWarning(HRESULT aResultCode, const char *aText, ...)
1138 {
1139 va_list args;
1140 va_start(args, aText);
1141 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setWarning(aResultCode,
1142 COM_IIDOF(I),
1143 C::getComponentName(),
1144 aText,
1145 args);
1146 va_end(args);
1147 return rc;
1148 }
1149
1150 /**
1151 * Sets the error information for the current thread, va_list variant.
1152 * A convenience method that automatically sets the default interface
1153 * ID (taken from the I template argument) and the component name
1154 * (a value of C::getComponentName()).
1155 *
1156 * See #setError(HRESULT, const GUID &, const wchar_t *, const char *text, ...)
1157 * and #setError(HRESULT, const char *, ...) for details.
1158 */
1159 static HRESULT setErrorV(HRESULT aResultCode, const char *aText,
1160 va_list aArgs)
1161 {
1162 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError(aResultCode,
1163 COM_IIDOF(I),
1164 C::getComponentName(),
1165 aText,
1166 aArgs,
1167 true /* aLogIt */);
1168 return rc;
1169 }
1170
1171 /**
1172 * This method is the same as #setErrorV() except that it makes sure @a
1173 * aResultCode doesn't have the error severity bit (31) set when passed
1174 * down to the created IVirtualBoxErrorInfo object.
1175 *
1176 * The error severity bit is always cleared by this call, thereof you can
1177 * use ordinary E_XXX result code constants, for convenience. However, this
1178 * behavior may be non-standard on some COM platforms.
1179 */
1180 static HRESULT setWarningV(HRESULT aResultCode, const char *aText,
1181 va_list aArgs)
1182 {
1183 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setWarning(aResultCode,
1184 COM_IIDOF(I),
1185 C::getComponentName(),
1186 aText,
1187 aArgs);
1188 return rc;
1189 }
1190
1191 /**
1192 * Sets the error information for the current thread.
1193 * A convenience method that automatically sets the component name
1194 * (a value of C::getComponentName()), but allows to specify the interface
1195 * id manually.
1196 *
1197 * See #setError(HRESULT, const GUID &, const wchar_t *, const char *text, ...)
1198 * for details.
1199 */
1200 static HRESULT setError(HRESULT aResultCode, const GUID &aIID,
1201 const char *aText, ...)
1202 {
1203 va_list args;
1204 va_start(args, aText);
1205 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError(aResultCode,
1206 aIID,
1207 C::getComponentName(),
1208 aText,
1209 args,
1210 true /* aLogIt */);
1211 va_end(args);
1212 return rc;
1213 }
1214
1215 /**
1216 * This method is the same as #setError() except that it makes sure @a
1217 * aResultCode doesn't have the error severity bit (31) set when passed
1218 * down to the created IVirtualBoxErrorInfo object.
1219 *
1220 * The error severity bit is always cleared by this call, thereof you can
1221 * use ordinary E_XXX result code constants, for convenience. However, this
1222 * behavior may be non-standard on some COM platforms.
1223 */
1224 static HRESULT setWarning(HRESULT aResultCode, const GUID &aIID,
1225 const char *aText, ...)
1226 {
1227 va_list args;
1228 va_start(args, aText);
1229 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setWarning(aResultCode,
1230 aIID,
1231 C::getComponentName(),
1232 aText,
1233 args);
1234 va_end(args);
1235 return rc;
1236 }
1237
1238 /**
1239 * Sets the error information for the current thread but doesn't put
1240 * anything in the release log. This is very useful for avoiding
1241 * harmless error from causing confusion.
1242 *
1243 * It is otherwise identical to #setError(HRESULT, const char *text, ...).
1244 */
1245 static HRESULT setErrorNoLog(HRESULT aResultCode, const char *aText, ...)
1246 {
1247 va_list args;
1248 va_start(args, aText);
1249 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError(aResultCode,
1250 COM_IIDOF(I),
1251 C::getComponentName(),
1252 aText,
1253 args,
1254 false /* aLogIt */);
1255 va_end(args);
1256 return rc;
1257 }
1258
1259private:
1260
1261};
1262
1263
1264/**
1265 * Base class to track VirtualBoxBaseNEXT chlidren of the component.
1266 *
1267 * This class is a preferrable VirtualBoxBase replacement for components that
1268 * operate with collections of child components. It gives two useful
1269 * possibilities:
1270 *
1271 * <ol><li>
1272 * Given an IUnknown instance, it's possible to quickly determine
1273 * whether this instance represents a child object that belongs to the
1274 * given component, and if so, get a valid VirtualBoxBase pointer to the
1275 * child object. The returned pointer can be then safely casted to the
1276 * actual class of the child object (to get access to its "internal"
1277 * non-interface methods) provided that no other child components implement
1278 * the same original COM interface IUnknown is queried from.
1279 * </li><li>
1280 * When the parent object uninitializes itself, it can easily unintialize
1281 * all its VirtualBoxBase derived children (using their
1282 * VirtualBoxBase::uninit() implementations). This is done simply by
1283 * calling the #uninitDependentChildren() method.
1284 * </li></ol>
1285 *
1286 * In order to let the above work, the following must be done:
1287 * <ol><li>
1288 * When a child object is initialized, it calls #addDependentChild() of
1289 * its parent to register itself within the list of dependent children.
1290 * </li><li>
1291 * When the child object it is uninitialized, it calls
1292 * #removeDependentChild() to unregister itself.
1293 * </li></ol>
1294 *
1295 * Note that if the parent object does not call #uninitDependentChildren() when
1296 * it gets uninitialized, it must call uninit() methods of individual children
1297 * manually to disconnect them; a failure to do so will cause crashes in these
1298 * methods when children get destroyed. The same applies to children not calling
1299 * #removeDependentChild() when getting destroyed.
1300 *
1301 * Note that children added by #addDependentChild() are <b>weakly</b> referenced
1302 * (i.e. AddRef() is not called), so when a child object is deleted externally
1303 * (because it's reference count goes to zero), it will automatically remove
1304 * itself from the map of dependent children provided that it follows the rules
1305 * described here.
1306 *
1307 * Access to the child list is serialized using the #childrenLock() lock handle
1308 * (which defaults to the general object lock handle (see
1309 * VirtualBoxBase::lockHandle()). This lock is used by all add/remove methods of
1310 * this class so be aware of the need to preserve the {parent, child} lock order
1311 * when calling these methods.
1312 *
1313 * Read individual method descriptions to get further information.
1314 *
1315 * @todo This is a VirtualBoxBaseWithChildren equivalent that uses the
1316 * VirtualBoxBaseNEXT implementation. Will completely supersede
1317 * VirtualBoxBaseWithChildren after the old VirtualBoxBase implementation
1318 * has gone.
1319 */
1320class VirtualBoxBaseWithChildrenNEXT : public VirtualBoxBase
1321{
1322public:
1323
1324 VirtualBoxBaseWithChildrenNEXT()
1325 {}
1326
1327 virtual ~VirtualBoxBaseWithChildrenNEXT()
1328 {}
1329
1330 /**
1331 * Lock handle to use when adding/removing child objects from the list of
1332 * children. It is guaranteed that no any other lock is requested in methods
1333 * of this class while holding this lock.
1334 *
1335 * @warning By default, this simply returns the general object's lock handle
1336 * (see VirtualBoxBase::lockHandle()) which is sufficient for most
1337 * cases.
1338 */
1339 virtual RWLockHandle *childrenLock() { return lockHandle(); }
1340
1341 /**
1342 * Adds the given child to the list of dependent children.
1343 *
1344 * Usually gets called from the child's init() method.
1345 *
1346 * @note @a aChild (unless it is in InInit state) must be protected by
1347 * VirtualBoxBase::AutoCaller to make sure it is not uninitialized on
1348 * another thread during this method's call.
1349 *
1350 * @note When #childrenLock() is not overloaded (returns the general object
1351 * lock) and this method is called from under the child's read or
1352 * write lock, make sure the {parent, child} locking order is
1353 * preserved by locking the callee (this object) for writing before
1354 * the child's lock.
1355 *
1356 * @param aChild Child object to add (must inherit VirtualBoxBase AND
1357 * implement some interface).
1358 *
1359 * @note Locks #childrenLock() for writing.
1360 */
1361 template<class C>
1362 void addDependentChild(C *aChild)
1363 {
1364 AssertReturnVoid(aChild != NULL);
1365 doAddDependentChild(ComPtr<IUnknown>(aChild), aChild);
1366 }
1367
1368 /**
1369 * Equivalent to template <class C> void addDependentChild (C *aChild)
1370 * but takes a ComObjPtr<C> argument.
1371 */
1372 template<class C>
1373 void addDependentChild(const ComObjPtr<C> &aChild)
1374 {
1375 AssertReturnVoid(!aChild.isNull());
1376 doAddDependentChild(ComPtr<IUnknown>(static_cast<C *>(aChild)), aChild);
1377 }
1378
1379 /**
1380 * Removes the given child from the list of dependent children.
1381 *
1382 * Usually gets called from the child's uninit() method.
1383 *
1384 * Keep in mind that the called (parent) object may be no longer available
1385 * (i.e. may be deleted deleted) after this method returns, so you must not
1386 * call any other parent's methods after that!
1387 *
1388 * @note Locks #childrenLock() for writing.
1389 *
1390 * @note @a aChild (unless it is in InUninit state) must be protected by
1391 * VirtualBoxBase::AutoCaller to make sure it is not uninitialized on
1392 * another thread during this method's call.
1393 *
1394 * @note When #childrenLock() is not overloaded (returns the general object
1395 * lock) and this method is called from under the child's read or
1396 * write lock, make sure the {parent, child} locking order is
1397 * preserved by locking the callee (this object) for writing before
1398 * the child's lock. This is irrelevant when the method is called from
1399 * under this object's VirtualBoxBaseProto::AutoUninitSpan (i.e. in
1400 * InUninit state) since in this case no locking is done.
1401 *
1402 * @param aChild Child object to remove.
1403 *
1404 * @note Locks #childrenLock() for writing.
1405 */
1406 template<class C>
1407 void removeDependentChild(C *aChild)
1408 {
1409 AssertReturnVoid(aChild != NULL);
1410 doRemoveDependentChild(ComPtr<IUnknown>(aChild));
1411 }
1412
1413 /**
1414 * Equivalent to template <class C> void removeDependentChild (C *aChild)
1415 * but takes a ComObjPtr<C> argument.
1416 */
1417 template<class C>
1418 void removeDependentChild(const ComObjPtr<C> &aChild)
1419 {
1420 AssertReturnVoid(!aChild.isNull());
1421 doRemoveDependentChild(ComPtr<IUnknown>(static_cast<C *>(aChild)));
1422 }
1423
1424protected:
1425
1426 void uninitDependentChildren();
1427
1428 VirtualBoxBase *getDependentChild(const ComPtr<IUnknown> &aUnk);
1429
1430private:
1431 void doAddDependentChild(IUnknown *aUnk, VirtualBoxBase *aChild);
1432 void doRemoveDependentChild(IUnknown *aUnk);
1433
1434 typedef std::map<IUnknown*, VirtualBoxBase*> DependentChildren;
1435 DependentChildren mDependentChildren;
1436};
1437
1438////////////////////////////////////////////////////////////////////////////////
1439
1440////////////////////////////////////////////////////////////////////////////////
1441
1442
1443/// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
1444/**
1445 * Simple template that manages data structure allocation/deallocation
1446 * and supports data pointer sharing (the instance that shares the pointer is
1447 * not responsible for memory deallocation as opposed to the instance that
1448 * owns it).
1449 */
1450template <class D>
1451class Shareable
1452{
1453public:
1454
1455 Shareable() : mData (NULL), mIsShared(FALSE) {}
1456 ~Shareable() { free(); }
1457
1458 void allocate() { attach(new D); }
1459
1460 virtual void free() {
1461 if (mData) {
1462 if (!mIsShared)
1463 delete mData;
1464 mData = NULL;
1465 mIsShared = false;
1466 }
1467 }
1468
1469 void attach(D *d) {
1470 AssertMsg(d, ("new data must not be NULL"));
1471 if (d && mData != d) {
1472 if (mData && !mIsShared)
1473 delete mData;
1474 mData = d;
1475 mIsShared = false;
1476 }
1477 }
1478
1479 void attach(Shareable &d) {
1480 AssertMsg(
1481 d.mData == mData || !d.mIsShared,
1482 ("new data must not be shared")
1483 );
1484 if (this != &d && !d.mIsShared) {
1485 attach(d.mData);
1486 d.mIsShared = true;
1487 }
1488 }
1489
1490 void share(D *d) {
1491 AssertMsg(d, ("new data must not be NULL"));
1492 if (mData != d) {
1493 if (mData && !mIsShared)
1494 delete mData;
1495 mData = d;
1496 mIsShared = true;
1497 }
1498 }
1499
1500 void share(const Shareable &d) { share(d.mData); }
1501
1502 void attachCopy(const D *d) {
1503 AssertMsg(d, ("data to copy must not be NULL"));
1504 if (d)
1505 attach(new D(*d));
1506 }
1507
1508 void attachCopy(const Shareable &d) {
1509 attachCopy(d.mData);
1510 }
1511
1512 virtual D *detach() {
1513 D *d = mData;
1514 mData = NULL;
1515 mIsShared = false;
1516 return d;
1517 }
1518
1519 D *data() const {
1520 return mData;
1521 }
1522
1523 D *operator->() const {
1524 AssertMsg(mData, ("data must not be NULL"));
1525 return mData;
1526 }
1527
1528 bool isNull() const { return mData == NULL; }
1529 bool operator!() const { return isNull(); }
1530
1531 bool isShared() const { return mIsShared; }
1532
1533protected:
1534
1535 D *mData;
1536 bool mIsShared;
1537};
1538
1539/// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
1540/**
1541 * Simple template that enhances Shareable<> and supports data
1542 * backup/rollback/commit (using the copy constructor of the managed data
1543 * structure).
1544 */
1545template<class D>
1546class Backupable : public Shareable<D>
1547{
1548public:
1549
1550 Backupable() : Shareable<D> (), mBackupData(NULL) {}
1551
1552 void free()
1553 {
1554 AssertMsg(this->mData || !mBackupData, ("backup must be NULL if data is NULL"));
1555 rollback();
1556 Shareable<D>::free();
1557 }
1558
1559 D *detach()
1560 {
1561 AssertMsg(this->mData || !mBackupData, ("backup must be NULL if data is NULL"));
1562 rollback();
1563 return Shareable<D>::detach();
1564 }
1565
1566 void share(const Backupable &d)
1567 {
1568 AssertMsg(!d.isBackedUp(), ("data to share must not be backed up"));
1569 if (!d.isBackedUp())
1570 Shareable<D>::share(d.mData);
1571 }
1572
1573 /**
1574 * Stores the current data pointer in the backup area, allocates new data
1575 * using the copy constructor on current data and makes new data active.
1576 */
1577 void backup()
1578 {
1579 AssertMsg(this->mData, ("data must not be NULL"));
1580 if (this->mData && !mBackupData)
1581 {
1582 D *pNewData = new D(*this->mData);
1583 mBackupData = this->mData;
1584 this->mData = pNewData;
1585 }
1586 }
1587
1588 /**
1589 * Deletes new data created by #backup() and restores previous data pointer
1590 * stored in the backup area, making it active again.
1591 */
1592 void rollback()
1593 {
1594 if (this->mData && mBackupData)
1595 {
1596 delete this->mData;
1597 this->mData = mBackupData;
1598 mBackupData = NULL;
1599 }
1600 }
1601
1602 /**
1603 * Commits current changes by deleting backed up data and clearing up the
1604 * backup area. The new data pointer created by #backup() remains active
1605 * and becomes the only managed pointer.
1606 *
1607 * This method is much faster than #commitCopy() (just a single pointer
1608 * assignment operation), but makes the previous data pointer invalid
1609 * (because it is freed). For this reason, this method must not be
1610 * used if it's possible that data managed by this instance is shared with
1611 * some other Shareable instance. See #commitCopy().
1612 */
1613 void commit()
1614 {
1615 if (this->mData && mBackupData)
1616 {
1617 if (!this->mIsShared)
1618 delete mBackupData;
1619 mBackupData = NULL;
1620 this->mIsShared = false;
1621 }
1622 }
1623
1624 /**
1625 * Commits current changes by assigning new data to the previous data
1626 * pointer stored in the backup area using the assignment operator.
1627 * New data is deleted, the backup area is cleared and the previous data
1628 * pointer becomes active and the only managed pointer.
1629 *
1630 * This method is slower than #commit(), but it keeps the previous data
1631 * pointer valid (i.e. new data is copied to the same memory location).
1632 * For that reason it's safe to use this method on instances that share
1633 * managed data with other Shareable instances.
1634 */
1635 void commitCopy()
1636 {
1637 if (this->mData && mBackupData)
1638 {
1639 *mBackupData = *(this->mData);
1640 delete this->mData;
1641 this->mData = mBackupData;
1642 mBackupData = NULL;
1643 }
1644 }
1645
1646 void assignCopy(const D *pData)
1647 {
1648 AssertMsg(this->mData, ("data must not be NULL"));
1649 AssertMsg(pData, ("data to copy must not be NULL"));
1650 if (this->mData && pData)
1651 {
1652 if (!mBackupData)
1653 {
1654 D *pNewData = new D(*pData);
1655 mBackupData = this->mData;
1656 this->mData = pNewData;
1657 }
1658 else
1659 *this->mData = *pData;
1660 }
1661 }
1662
1663 void assignCopy(const Backupable &d)
1664 {
1665 assignCopy(d.mData);
1666 }
1667
1668 bool isBackedUp() const
1669 {
1670 return mBackupData != NULL;
1671 }
1672
1673 D *backedUpData() const
1674 {
1675 return mBackupData;
1676 }
1677
1678protected:
1679
1680 D *mBackupData;
1681};
1682
1683#endif // !____H_VIRTUALBOXBASEIMPL
1684
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