VirtualBox

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

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

Main: finish integration of Main lock validation with IPRT; only enabled with VBOX_WITH_STRICT_LOCKS=1 (do NOT enable unless you want Main to stop working now)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 80.4 KB
Line 
1/** @file
2 *
3 * VirtualBox COM base classes definition
4 */
5
6/*
7 * Copyright (C) 2006-2009 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. 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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#ifndef ____H_VIRTUALBOXBASEIMPL
23#define ____H_VIRTUALBOXBASEIMPL
24
25#include <iprt/cdefs.h>
26#include <iprt/thread.h>
27
28#include <list>
29#include <map>
30
31#include "VBox/com/ErrorInfo.h"
32#include "VBox/com/SupportErrorInfo.h"
33#include "VBox/com/AutoLock.h"
34
35#include "VBox/com/VirtualBox.h"
36
37// avoid including VBox/settings.h and VBox/xml.h;
38// only declare the classes
39namespace xml
40{
41class File;
42}
43
44using namespace com;
45using namespace util;
46
47#if !defined (VBOX_WITH_XPCOM)
48
49#include <atlcom.h>
50
51/* use a special version of the singleton class factory,
52 * see KB811591 in msdn for more info. */
53
54#undef DECLARE_CLASSFACTORY_SINGLETON
55#define DECLARE_CLASSFACTORY_SINGLETON(obj) DECLARE_CLASSFACTORY_EX(CMyComClassFactorySingleton<obj>)
56
57template <class T>
58class CMyComClassFactorySingleton : public CComClassFactory
59{
60public:
61 CMyComClassFactorySingleton() : m_hrCreate(S_OK){}
62 virtual ~CMyComClassFactorySingleton(){}
63 // IClassFactory
64 STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj)
65 {
66 HRESULT hRes = E_POINTER;
67 if (ppvObj != NULL)
68 {
69 *ppvObj = NULL;
70 // Aggregation is not supported in singleton objects.
71 ATLASSERT(pUnkOuter == NULL);
72 if (pUnkOuter != NULL)
73 hRes = CLASS_E_NOAGGREGATION;
74 else
75 {
76 if (m_hrCreate == S_OK && m_spObj == NULL)
77 {
78 Lock();
79 __try
80 {
81 // Fix: The following If statement was moved inside the __try statement.
82 // Did another thread arrive here first?
83 if (m_hrCreate == S_OK && m_spObj == NULL)
84 {
85 // lock the module to indicate activity
86 // (necessary for the monitor shutdown thread to correctly
87 // terminate the module in case when CreateInstance() fails)
88 _pAtlModule->Lock();
89 CComObjectCached<T> *p;
90 m_hrCreate = CComObjectCached<T>::CreateInstance(&p);
91 if (SUCCEEDED(m_hrCreate))
92 {
93 m_hrCreate = p->QueryInterface(IID_IUnknown, (void**)&m_spObj);
94 if (FAILED(m_hrCreate))
95 {
96 delete p;
97 }
98 }
99 _pAtlModule->Unlock();
100 }
101 }
102 __finally
103 {
104 Unlock();
105 }
106 }
107 if (m_hrCreate == S_OK)
108 {
109 hRes = m_spObj->QueryInterface(riid, ppvObj);
110 }
111 else
112 {
113 hRes = m_hrCreate;
114 }
115 }
116 }
117 return hRes;
118 }
119 HRESULT m_hrCreate;
120 CComPtr<IUnknown> m_spObj;
121};
122
123#endif /* !defined (VBOX_WITH_XPCOM) */
124
125// macros
126////////////////////////////////////////////////////////////////////////////////
127
128/**
129 * Special version of the Assert macro to be used within VirtualBoxBase
130 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
131 *
132 * In the debug build, this macro is equivalent to Assert.
133 * In the release build, this macro uses |setError (E_FAIL, ...)| to set the
134 * error info from the asserted expression.
135 *
136 * @see VirtualBoxSupportErrorInfoImpl::setError
137 *
138 * @param expr Expression which should be true.
139 */
140#if defined (DEBUG)
141#define ComAssert(expr) Assert(expr)
142#else
143#define ComAssert(expr) \
144 do { \
145 if (RT_UNLIKELY(!(expr))) \
146 setError(E_FAIL, "Assertion failed: [%s] at '%s' (%d) in %s.\n" \
147 "Please contact the product vendor!", \
148 #expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
149 } while (0)
150#endif
151
152/**
153 * Special version of the AssertMsg macro to be used within VirtualBoxBase
154 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
155 *
156 * See ComAssert for more info.
157 *
158 * @param expr Expression which should be true.
159 * @param a printf argument list (in parenthesis).
160 */
161#if defined (DEBUG)
162#define ComAssertMsg(expr, a) AssertMsg(expr, a)
163#else
164#define ComAssertMsg(expr, a) \
165 do { \
166 if (RT_UNLIKELY(!(expr))) \
167 setError(E_FAIL, "Assertion failed: [%s] at '%s' (%d) in %s.\n" \
168 "%s.\n" \
169 "Please contact the product vendor!", \
170 #expr, __FILE__, __LINE__, __PRETTY_FUNCTION__, Utf8StrFmt a .raw()); \
171 } while (0)
172#endif
173
174/**
175 * Special version of the AssertRC macro to be used within VirtualBoxBase
176 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
177 *
178 * See ComAssert for more info.
179 *
180 * @param vrc VBox status code.
181 */
182#if defined (DEBUG)
183#define ComAssertRC(vrc) AssertRC(vrc)
184#else
185#define ComAssertRC(vrc) ComAssertMsgRC(vrc, ("%Rra", vrc))
186#endif
187
188/**
189 * Special version of the AssertMsgRC macro to be used within VirtualBoxBase
190 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
191 *
192 * See ComAssert for more info.
193 *
194 * @param vrc VBox status code.
195 * @param msg printf argument list (in parenthesis).
196 */
197#if defined (DEBUG)
198#define ComAssertMsgRC(vrc, msg) AssertMsgRC(vrc, msg)
199#else
200#define ComAssertMsgRC(vrc, msg) ComAssertMsg(RT_SUCCESS(vrc), msg)
201#endif
202
203/**
204 * Special version of the AssertComRC macro to be used within VirtualBoxBase
205 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
206 *
207 * See ComAssert for more info.
208 *
209 * @param rc COM result code
210 */
211#if defined (DEBUG)
212#define ComAssertComRC(rc) AssertComRC(rc)
213#else
214#define ComAssertComRC(rc) ComAssertMsg(SUCCEEDED(rc), ("COM RC = %Rhrc (0x%08X)", (rc), (rc)))
215#endif
216
217
218/** Special version of ComAssert that returns ret if expr fails */
219#define ComAssertRet(expr, ret) \
220 do { ComAssert(expr); if (!(expr)) return (ret); } while (0)
221/** Special version of ComAssertMsg that returns ret if expr fails */
222#define ComAssertMsgRet(expr, a, ret) \
223 do { ComAssertMsg(expr, a); if (!(expr)) return (ret); } while (0)
224/** Special version of ComAssertRC that returns ret if vrc does not succeed */
225#define ComAssertRCRet(vrc, ret) \
226 do { ComAssertRC(vrc); if (!RT_SUCCESS(vrc)) return (ret); } while (0)
227/** Special version of ComAssertMsgRC that returns ret if vrc does not succeed */
228#define ComAssertMsgRCRet(vrc, msg, ret) \
229 do { ComAssertMsgRC(vrc, msg); if (!RT_SUCCESS(vrc)) return (ret); } while (0)
230/** Special version of ComAssertFailed that returns ret */
231#define ComAssertFailedRet(ret) \
232 do { ComAssertFailed(); return (ret); } while (0)
233/** Special version of ComAssertMsgFailed that returns ret */
234#define ComAssertMsgFailedRet(msg, ret) \
235 do { ComAssertMsgFailed(msg); return (ret); } while (0)
236/** Special version of ComAssertComRC that returns ret if rc does not succeed */
237#define ComAssertComRCRet(rc, ret) \
238 do { ComAssertComRC(rc); if (!SUCCEEDED(rc)) return (ret); } while (0)
239/** Special version of ComAssertComRC that returns rc if rc does not succeed */
240#define ComAssertComRCRetRC(rc) \
241 do { ComAssertComRC(rc); if (!SUCCEEDED(rc)) return (rc); } while (0)
242
243
244/** Special version of ComAssert that evaluates eval and breaks if expr fails */
245#define ComAssertBreak(expr, eval) \
246 if (1) { ComAssert(expr); if (!(expr)) { eval; break; } } else do {} while (0)
247/** Special version of ComAssertMsg that evaluates eval and breaks if expr fails */
248#define ComAssertMsgBreak(expr, a, eval) \
249 if (1) { ComAssertMsg(expr, a); if (!(expr)) { eval; break; } } else do {} while (0)
250/** Special version of ComAssertRC that evaluates eval and breaks if vrc does not succeed */
251#define ComAssertRCBreak(vrc, eval) \
252 if (1) { ComAssertRC(vrc); if (!RT_SUCCESS(vrc)) { eval; break; } } else do {} while (0)
253/** Special version of ComAssertMsgRC that evaluates eval and breaks if vrc does not succeed */
254#define ComAssertMsgRCBreak(vrc, msg, eval) \
255 if (1) { ComAssertMsgRC(vrc, msg); if (!RT_SUCCESS(vrc)) { eval; break; } } else do {} while (0)
256/** Special version of ComAssertFailed that evaluates eval and breaks */
257#define ComAssertFailedBreak(eval) \
258 if (1) { ComAssertFailed(); { eval; break; } } else do {} while (0)
259/** Special version of ComAssertMsgFailed that evaluates eval and breaks */
260#define ComAssertMsgFailedBreak(msg, eval) \
261 if (1) { ComAssertMsgFailed (msg); { eval; break; } } else do {} while (0)
262/** Special version of ComAssertComRC that evaluates eval and breaks if rc does not succeed */
263#define ComAssertComRCBreak(rc, eval) \
264 if (1) { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { eval; break; } } else do {} while (0)
265/** Special version of ComAssertComRC that just breaks if rc does not succeed */
266#define ComAssertComRCBreakRC(rc) \
267 if (1) { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { break; } } else do {} while (0)
268
269
270/** Special version of ComAssert that evaluates eval and throws it if expr fails */
271#define ComAssertThrow(expr, eval) \
272 if (1) { ComAssert(expr); if (!(expr)) { throw (eval); } } else do {} while (0)
273/** Special version of ComAssertMsg that evaluates eval and throws it if expr fails */
274#define ComAssertMsgThrow(expr, a, eval) \
275 if (1) { ComAssertMsg(expr, a); if (!(expr)) { throw (eval); } } else do {} while (0)
276/** Special version of ComAssertRC that evaluates eval and throws it if vrc does not succeed */
277#define ComAssertRCThrow(vrc, eval) \
278 if (1) { ComAssertRC(vrc); if (!RT_SUCCESS(vrc)) { throw (eval); } } else do {} while (0)
279/** Special version of ComAssertMsgRC that evaluates eval and throws it if vrc does not succeed */
280#define ComAssertMsgRCThrow(vrc, msg, eval) \
281 if (1) { ComAssertMsgRC(vrc, msg); if (!RT_SUCCESS(vrc)) { throw (eval); } } else do {} while (0)
282/** Special version of ComAssertFailed that evaluates eval and throws it */
283#define ComAssertFailedThrow(eval) \
284 if (1) { ComAssertFailed(); { throw (eval); } } else do {} while (0)
285/** Special version of ComAssertMsgFailed that evaluates eval and throws it */
286#define ComAssertMsgFailedThrow(msg, eval) \
287 if (1) { ComAssertMsgFailed (msg); { throw (eval); } } else do {} while (0)
288/** Special version of ComAssertComRC that evaluates eval and throws it if rc does not succeed */
289#define ComAssertComRCThrow(rc, eval) \
290 if (1) { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { throw (eval); } } else do {} while (0)
291/** Special version of ComAssertComRC that just throws rc if rc does not succeed */
292#define ComAssertComRCThrowRC(rc) \
293 if (1) { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { throw rc; } } else do {} while (0)
294
295////////////////////////////////////////////////////////////////////////////////
296
297/**
298 * Checks that the pointer argument is not NULL and returns E_INVALIDARG +
299 * extended error info on failure.
300 * @param arg Input pointer-type argument (strings, interface pointers...)
301 */
302#define CheckComArgNotNull(arg) \
303 do { \
304 if (RT_UNLIKELY((arg) == NULL)) \
305 return setError(E_INVALIDARG, tr("Argument %s is NULL"), #arg); \
306 } while (0)
307
308/**
309 * Checks that safe array argument is not NULL and returns E_INVALIDARG +
310 * extended error info on failure.
311 * @param arg Input safe array argument (strings, interface pointers...)
312 */
313#define CheckComArgSafeArrayNotNull(arg) \
314 do { \
315 if (RT_UNLIKELY(ComSafeArrayInIsNull(arg))) \
316 return setError(E_INVALIDARG, tr("Argument %s is NULL"), #arg); \
317 } while (0)
318
319/**
320 * Checks that the string argument is not a NULL or empty string and returns
321 * E_INVALIDARG + extended error info on failure.
322 * @param arg Input string argument (BSTR etc.).
323 */
324#define CheckComArgStrNotEmptyOrNull(arg) \
325 do { \
326 if (RT_UNLIKELY((arg) == NULL || *(arg) == '\0')) \
327 return setError(E_INVALIDARG, \
328 tr("Argument %s is empty or NULL"), #arg); \
329 } while (0)
330
331/**
332 * Checks that the given expression (that must involve the argument) is true and
333 * returns E_INVALIDARG + extended error info on failure.
334 * @param arg Argument.
335 * @param expr Expression to evaluate.
336 */
337#define CheckComArgExpr(arg, expr) \
338 do { \
339 if (RT_UNLIKELY(!(expr))) \
340 return setError(E_INVALIDARG, \
341 tr("Argument %s is invalid (must be %s)"), #arg, #expr); \
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. The error message must
347 * be customized.
348 * @param arg Argument.
349 * @param expr Expression to evaluate.
350 * @param msg Parenthesized printf-like expression (must start with a verb,
351 * like "must be one of...", "is not within...").
352 */
353#define CheckComArgExprMsg(arg, expr, msg) \
354 do { \
355 if (RT_UNLIKELY(!(expr))) \
356 return setError(E_INVALIDARG, tr ("Argument %s %s"), \
357 #arg, Utf8StrFmt msg .raw()); \
358 } while (0)
359
360/**
361 * Checks that the given pointer to an output argument is valid and returns
362 * E_POINTER + extended error info otherwise.
363 * @param arg Pointer argument.
364 */
365#define CheckComArgOutPointerValid(arg) \
366 do { \
367 if (RT_UNLIKELY(!VALID_PTR(arg))) \
368 return setError(E_POINTER, \
369 tr("Output argument %s points to invalid memory location (%p)"), \
370 #arg, (void *) (arg)); \
371 } while (0)
372
373/**
374 * Checks that the given pointer to an output safe array argument is valid and
375 * returns E_POINTER + extended error info otherwise.
376 * @param arg Safe array argument.
377 */
378#define CheckComArgOutSafeArrayPointerValid(arg) \
379 do { \
380 if (RT_UNLIKELY(ComSafeArrayOutIsNull(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 * Sets the extended error info and returns E_NOTIMPL.
388 */
389#define ReturnComNotImplemented() \
390 do { \
391 return setError(E_NOTIMPL, tr("Method %s is not implemented"), __FUNCTION__); \
392 } while (0)
393
394////////////////////////////////////////////////////////////////////////////////
395
396/**
397 * Declares an empty constructor and destructor for the given class.
398 * This is useful to prevent the compiler from generating the default
399 * ctor and dtor, which in turn allows to use forward class statements
400 * (instead of including their header files) when declaring data members of
401 * non-fundamental types with constructors (which are always called implicitly
402 * by constructors and by the destructor of the class).
403 *
404 * This macro is to be placed within (the public section of) the class
405 * declaration. Its counterpart, DEFINE_EMPTY_CTOR_DTOR, must be placed
406 * somewhere in one of the translation units (usually .cpp source files).
407 *
408 * @param cls class to declare a ctor and dtor for
409 */
410#define DECLARE_EMPTY_CTOR_DTOR(cls) cls(); ~cls();
411
412/**
413 * Defines an empty constructor and destructor for the given class.
414 * See DECLARE_EMPTY_CTOR_DTOR for more info.
415 */
416#define DEFINE_EMPTY_CTOR_DTOR(cls) \
417 cls::cls () {}; cls::~cls () {};
418
419////////////////////////////////////////////////////////////////////////////////
420
421enum VBoxClsID
422{
423 clsidVirtualBox,
424 clsidHost,
425 clsidMachine,
426 clsidSessionMachine,
427 clsidSnapshotMachine,
428 clsidSnapshot,
429 clsidOther
430};
431
432/**
433 * Abstract base class for all component classes implementing COM
434 * interfaces of the VirtualBox COM library.
435 *
436 * Declares functionality that should be available in all components.
437 *
438 * Note that this class is always subclassed using the virtual keyword so
439 * that only one instance of its VTBL and data is present in each derived class
440 * even in case if VirtualBoxBaseProto appears more than once among base classes
441 * of the particular component as a result of multiple inheritance.
442 *
443 * This makes it possible to have intermediate base classes used by several
444 * components that implement some common interface functionality but still let
445 * the final component classes choose what VirtualBoxBase variant it wants to
446 * use.
447 *
448 * Among the basic functionality implemented by this class is the primary object
449 * state that indicates if the object is ready to serve the calls, and if not,
450 * what stage it is currently at. Here is the primary state diagram:
451 *
452 * +-------------------------------------------------------+
453 * | |
454 * | (InitFailed) -----------------------+ |
455 * | ^ | |
456 * v | v |
457 * [*] ---> NotReady ----> (InInit) -----> Ready -----> (InUninit) ----+
458 * ^ | ^ | ^
459 * | v | v |
460 * | Limited | (MayUninit) --> (WillUninit)
461 * | | | |
462 * +-------+ +-------+
463 *
464 * The object is fully operational only when its state is Ready. The Limited
465 * state means that only some vital part of the object is operational, and it
466 * requires some sort of reinitialization to become fully operational. The
467 * NotReady state means the object is basically dead: it either was not yet
468 * initialized after creation at all, or was uninitialized and is waiting to be
469 * destroyed when the last reference to it is released. All other states are
470 * transitional.
471 *
472 * The NotReady->InInit->Ready, NotReady->InInit->Limited and
473 * NotReady->InInit->InitFailed transition is done by the AutoInitSpan smart
474 * class.
475 *
476 * The Limited->InInit->Ready, Limited->InInit->Limited and
477 * Limited->InInit->InitFailed transition is done by the AutoReinitSpan smart
478 * class.
479 *
480 * The Ready->InUninit->NotReady, InitFailed->InUninit->NotReady and
481 * WillUninit->InUninit->NotReady transitions are done by the AutoUninitSpan
482 * smart class.
483 *
484 * The Ready->MayUninit->Ready and Ready->MayUninit->WillUninit transitions are
485 * done by the AutoMayUninitSpan smart class.
486 *
487 * In order to maintain the primary state integrity and declared functionality
488 * all subclasses must:
489 *
490 * 1) Use the above Auto*Span classes to perform state transitions. See the
491 * individual class descriptions for details.
492 *
493 * 2) All public methods of subclasses (i.e. all methods that can be called
494 * directly, not only from within other methods of the subclass) must have a
495 * standard prolog as described in the AutoCaller and AutoLimitedCaller
496 * documentation. Alternatively, they must use addCaller()/releaseCaller()
497 * directly (and therefore have both the prolog and the epilog), but this is
498 * not recommended.
499 */
500class ATL_NO_VTABLE VirtualBoxBaseProto : public Lockable
501{
502public:
503
504 enum State { NotReady, Ready, InInit, InUninit, InitFailed, Limited,
505 MayUninit, WillUninit };
506
507protected:
508
509 VirtualBoxBaseProto();
510 virtual ~VirtualBoxBaseProto();
511
512public:
513
514 // util::Lockable interface
515 virtual RWLockHandle *lockHandle() const;
516
517 /**
518 * Simple run-time type identification without having to enable C++ RTTI.
519 * The class IDs are defined in VirtualBoxBase.h.
520 * @return
521 */
522 virtual VBoxClsID getClassID() const
523 {
524 return clsidOther;
525 }
526
527 /**
528 * Override of the default locking class to be used for validating lock
529 * order with the standard member lock handle.
530 */
531 virtual VBoxLockingClass getLockingClass() const
532 {
533 return LOCKCLASS_OTHEROBJECT;
534 }
535
536 /**
537 * Unintialization method.
538 *
539 * Must be called by all final implementations (component classes) when the
540 * last reference to the object is released, before calling the destructor.
541 *
542 * This method is also automatically called by the uninit() method of this
543 * object's parent if this object is a dependent child of a class derived
544 * from VirtualBoxBaseWithChildren (see
545 * VirtualBoxBaseWithChildren::addDependentChild).
546 *
547 * @note Never call this method the AutoCaller scope or after the
548 * #addCaller() call not paired by #releaseCaller() because it is a
549 * guaranteed deadlock. See AutoUninitSpan for details.
550 */
551 virtual void uninit() {}
552
553 virtual HRESULT addCaller(State *aState = NULL, bool aLimited = false);
554 virtual void releaseCaller();
555
556 /**
557 * Adds a limited caller. This method is equivalent to doing
558 * <tt>addCaller (aState, true)</tt>, but it is preferred because provides
559 * better self-descriptiveness. See #addCaller() for more info.
560 */
561 HRESULT addLimitedCaller(State *aState = NULL)
562 {
563 return addCaller(aState, true /* aLimited */);
564 }
565
566 /**
567 * Smart class that automatically increases the number of callers of the
568 * given VirtualBoxBase object when an instance is constructed and decreases
569 * it back when the created instance goes out of scope (i.e. gets destroyed).
570 *
571 * If #rc() returns a failure after the instance creation, it means that
572 * the managed VirtualBoxBase object is not Ready, or in any other invalid
573 * state, so that the caller must not use the object and can return this
574 * failed result code to the upper level.
575 *
576 * See VirtualBoxBase::addCaller(), VirtualBoxBase::addLimitedCaller() and
577 * VirtualBoxBase::releaseCaller() for more details about object callers.
578 *
579 * @param aLimited |false| if this template should use
580 * VirtualiBoxBase::addCaller() calls to add callers, or
581 * |true| if VirtualiBoxBase::addLimitedCaller() should be
582 * used.
583 *
584 * @note It is preferable to use the AutoCaller and AutoLimitedCaller
585 * classes than specify the @a aLimited argument, for better
586 * self-descriptiveness.
587 */
588 template<bool aLimited>
589 class AutoCallerBase
590 {
591 public:
592
593 /**
594 * Increases the number of callers of the given object by calling
595 * VirtualBoxBase::addCaller().
596 *
597 * @param aObj Object to add a caller to. If NULL, this
598 * instance is effectively turned to no-op (where
599 * rc() will return S_OK and state() will be
600 * NotReady).
601 */
602 AutoCallerBase(VirtualBoxBaseProto *aObj)
603 : mObj(aObj)
604 , mRC(S_OK)
605 , mState(NotReady)
606 {
607 if (mObj)
608 mRC = mObj->addCaller(&mState, aLimited);
609 }
610
611 /**
612 * If the number of callers was successfully increased, decreases it
613 * using VirtualBoxBase::releaseCaller(), otherwise does nothing.
614 */
615 ~AutoCallerBase()
616 {
617 if (mObj && SUCCEEDED(mRC))
618 mObj->releaseCaller();
619 }
620
621 /**
622 * Stores the result code returned by VirtualBoxBase::addCaller() after
623 * instance creation or after the last #add() call. A successful result
624 * code means the number of callers was successfully increased.
625 */
626 HRESULT rc() const { return mRC; }
627
628 /**
629 * Returns |true| if |SUCCEEDED (rc())| is |true|, for convenience.
630 * |true| means the number of callers was successfully increased.
631 */
632 bool isOk() const { return SUCCEEDED(mRC); }
633
634 /**
635 * Stores the object state returned by VirtualBoxBase::addCaller() after
636 * instance creation or after the last #add() call.
637 */
638 State state() const { return mState; }
639
640 /**
641 * Temporarily decreases the number of callers of the managed object.
642 * May only be called if #isOk() returns |true|. Note that #rc() will
643 * return E_FAIL after this method succeeds.
644 */
645 void release()
646 {
647 Assert(SUCCEEDED(mRC));
648 if (SUCCEEDED(mRC))
649 {
650 if (mObj)
651 mObj->releaseCaller();
652 mRC = E_FAIL;
653 }
654 }
655
656 /**
657 * Restores the number of callers decreased by #release(). May only be
658 * called after #release().
659 */
660 void add()
661 {
662 Assert(!SUCCEEDED(mRC));
663 if (mObj && !SUCCEEDED(mRC))
664 mRC = mObj->addCaller(&mState, aLimited);
665 }
666
667 /**
668 * Attaches another object to this caller instance.
669 * The previous object's caller is released before the new one is added.
670 *
671 * @param aObj New object to attach, may be @c NULL.
672 */
673 void attach(VirtualBoxBaseProto *aObj)
674 {
675 /* detect simple self-reattachment */
676 if (mObj != aObj)
677 {
678 if (mObj && SUCCEEDED(mRC))
679 release();
680 mObj = aObj;
681 add();
682 }
683 }
684
685 /** Verbose equivalent to <tt>attach (NULL)</tt>. */
686 void detach() { attach(NULL); }
687
688 private:
689
690 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoCallerBase)
691 DECLARE_CLS_NEW_DELETE_NOOP(AutoCallerBase)
692
693 VirtualBoxBaseProto *mObj;
694 HRESULT mRC;
695 State mState;
696 };
697
698 /**
699 * Smart class that automatically increases the number of normal
700 * (non-limited) callers of the given VirtualBoxBase object when an instance
701 * is constructed and decreases it back when the created instance goes out
702 * of scope (i.e. gets destroyed).
703 *
704 * A typical usage pattern to declare a normal method of some object (i.e. a
705 * method that is valid only when the object provides its full
706 * functionality) is:
707 * <code>
708 * STDMETHODIMP Component::Foo()
709 * {
710 * AutoCaller autoCaller(this);
711 * if (FAILED(autoCaller.rc())) return autoCaller.rc();
712 * ...
713 * </code>
714 *
715 * Using this class is equivalent to using the AutoCallerBase template with
716 * the @a aLimited argument set to |false|, but this class is preferred
717 * because provides better self-descriptiveness.
718 *
719 * See AutoCallerBase for more information about auto caller functionality.
720 */
721 typedef AutoCallerBase<false> AutoCaller;
722
723 /**
724 * Smart class that automatically increases the number of limited callers of
725 * the given VirtualBoxBase object when an instance is constructed and
726 * decreases it back when the created instance goes out of scope (i.e. gets
727 * destroyed).
728 *
729 * A typical usage pattern to declare a limited method of some object (i.e.
730 * a method that is valid even if the object doesn't provide its full
731 * functionality) is:
732 * <code>
733 * STDMETHODIMP Component::Bar()
734 * {
735 * AutoLimitedCaller autoCaller(this);
736 * if (FAILED(autoCaller.rc())) return autoCaller.rc();
737 * ...
738 * </code>
739 *
740 * Using this class is equivalent to using the AutoCallerBase template with
741 * the @a aLimited argument set to |true|, but this class is preferred
742 * because provides better self-descriptiveness.
743 *
744 * See AutoCallerBase for more information about auto caller functionality.
745 */
746 typedef AutoCallerBase<true> AutoLimitedCaller;
747
748protected:
749
750 /**
751 * Smart class to enclose the state transition NotReady->InInit->Ready.
752 *
753 * The purpose of this span is to protect object initialization.
754 *
755 * Instances must be created as a stack-based variable taking |this| pointer
756 * as the argument at the beginning of init() methods of VirtualBoxBase
757 * subclasses. When this variable is created it automatically places the
758 * object to the InInit state.
759 *
760 * When the created variable goes out of scope (i.e. gets destroyed) then,
761 * depending on the result status of this initialization span, it either
762 * places the object to Ready or Limited state or calls the object's
763 * VirtualBoxBase::uninit() method which is supposed to place the object
764 * back to the NotReady state using the AutoUninitSpan class.
765 *
766 * The initial result status of the initialization span is determined by the
767 * @a aResult argument of the AutoInitSpan constructor (Result::Failed by
768 * default). Inside the initialization span, the success status can be set
769 * to Result::Succeeded using #setSucceeded(), to to Result::Limited using
770 * #setLimited() or to Result::Failed using #setFailed(). Please don't
771 * forget to set the correct success status before getting the AutoInitSpan
772 * variable destroyed (for example, by performing an early return from
773 * the init() method)!
774 *
775 * Note that if an instance of this class gets constructed when the object
776 * is in the state other than NotReady, #isOk() returns |false| and methods
777 * of this class do nothing: the state transition is not performed.
778 *
779 * A typical usage pattern is:
780 * <code>
781 * HRESULT Component::init()
782 * {
783 * AutoInitSpan autoInitSpan (this);
784 * AssertReturn (autoInitSpan.isOk(), E_FAIL);
785 * ...
786 * if (FAILED (rc))
787 * return rc;
788 * ...
789 * if (SUCCEEDED (rc))
790 * autoInitSpan.setSucceeded();
791 * return rc;
792 * }
793 * </code>
794 *
795 * @note Never create instances of this class outside init() methods of
796 * VirtualBoxBase subclasses and never pass anything other than |this|
797 * as the argument to the constructor!
798 */
799 class AutoInitSpan
800 {
801 public:
802
803 enum Result { Failed = 0x0, Succeeded = 0x1, Limited = 0x2 };
804
805 AutoInitSpan(VirtualBoxBaseProto *aObj, Result aResult = Failed);
806 ~AutoInitSpan();
807
808 /**
809 * Returns |true| if this instance has been created at the right moment
810 * (when the object was in the NotReady state) and |false| otherwise.
811 */
812 bool isOk() const { return mOk; }
813
814 /**
815 * Sets the initialization status to Succeeded to indicates successful
816 * initialization. The AutoInitSpan destructor will place the managed
817 * VirtualBoxBase object to the Ready state.
818 */
819 void setSucceeded() { mResult = Succeeded; }
820
821 /**
822 * Sets the initialization status to Succeeded to indicate limited
823 * (partly successful) initialization. The AutoInitSpan destructor will
824 * place the managed VirtualBoxBase object to the Limited state.
825 */
826 void setLimited() { mResult = Limited; }
827
828 /**
829 * Sets the initialization status to Failure to indicates failed
830 * initialization. The AutoInitSpan destructor will place the managed
831 * VirtualBoxBase object to the InitFailed state and will automatically
832 * call its uninit() method which is supposed to place the object back
833 * to the NotReady state using AutoUninitSpan.
834 */
835 void setFailed() { mResult = Failed; }
836
837 /** Returns the current initialization result. */
838 Result result() { return mResult; }
839
840 private:
841
842 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoInitSpan)
843 DECLARE_CLS_NEW_DELETE_NOOP(AutoInitSpan)
844
845 VirtualBoxBaseProto *mObj;
846 Result mResult : 3; // must be at least total number of bits + 1 (sign)
847 bool mOk : 1;
848 };
849
850 /**
851 * Smart class to enclose the state transition Limited->InInit->Ready.
852 *
853 * The purpose of this span is to protect object re-initialization.
854 *
855 * Instances must be created as a stack-based variable taking |this| pointer
856 * as the argument at the beginning of methods of VirtualBoxBase
857 * subclasses that try to re-initialize the object to bring it to the Ready
858 * state (full functionality) after partial initialization (limited
859 * functionality). When this variable is created, it automatically places
860 * the object to the InInit state.
861 *
862 * When the created variable goes out of scope (i.e. gets destroyed),
863 * depending on the success status of this initialization span, it either
864 * places the object to the Ready state or brings it back to the Limited
865 * state.
866 *
867 * The initial success status of the re-initialization span is |false|. In
868 * order to make it successful, #setSucceeded() must be called before the
869 * instance is destroyed.
870 *
871 * Note that if an instance of this class gets constructed when the object
872 * is in the state other than Limited, #isOk() returns |false| and methods
873 * of this class do nothing: the state transition is not performed.
874 *
875 * A typical usage pattern is:
876 * <code>
877 * HRESULT Component::reinit()
878 * {
879 * AutoReinitSpan autoReinitSpan (this);
880 * AssertReturn (autoReinitSpan.isOk(), E_FAIL);
881 * ...
882 * if (FAILED (rc))
883 * return rc;
884 * ...
885 * if (SUCCEEDED (rc))
886 * autoReinitSpan.setSucceeded();
887 * return rc;
888 * }
889 * </code>
890 *
891 * @note Never create instances of this class outside re-initialization
892 * methods of VirtualBoxBase subclasses and never pass anything other than
893 * |this| as the argument to the constructor!
894 */
895 class AutoReinitSpan
896 {
897 public:
898
899 AutoReinitSpan(VirtualBoxBaseProto *aObj);
900 ~AutoReinitSpan();
901
902 /**
903 * Returns |true| if this instance has been created at the right moment
904 * (when the object was in the Limited state) and |false| otherwise.
905 */
906 bool isOk() const { return mOk; }
907
908 /**
909 * Sets the re-initialization status to Succeeded to indicates
910 * successful re-initialization. The AutoReinitSpan destructor will place
911 * the managed VirtualBoxBase object to the Ready state.
912 */
913 void setSucceeded() { mSucceeded = true; }
914
915 private:
916
917 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoReinitSpan)
918 DECLARE_CLS_NEW_DELETE_NOOP(AutoReinitSpan)
919
920 VirtualBoxBaseProto *mObj;
921 bool mSucceeded : 1;
922 bool mOk : 1;
923 };
924
925 /**
926 * Smart class to enclose the state transition Ready->InUnnit->NotReady,
927 * InitFailed->InUnnit->NotReady or WillUninit->InUnnit->NotReady.
928 *
929 * The purpose of this span is to protect object uninitialization.
930 *
931 * Instances must be created as a stack-based variable taking |this| pointer
932 * as the argument at the beginning of uninit() methods of VirtualBoxBase
933 * subclasses. When this variable is created it automatically places the
934 * object to the InUninit state, unless it is already in the NotReady state
935 * as indicated by #uninitDone() returning |true|. In the latter case, the
936 * uninit() method must immediately return because there should be nothing
937 * to uninitialize.
938 *
939 * When this variable goes out of scope (i.e. gets destroyed), it places the
940 * object to NotReady state.
941 *
942 * A typical usage pattern is:
943 * <code>
944 * void Component::uninit()
945 * {
946 * AutoUninitSpan autoUninitSpan (this);
947 * if (autoUninitSpan.uninitDone())
948 * return;
949 * ...
950 * }
951 * </code>
952 *
953 * @note The constructor of this class blocks the current thread execution
954 * until the number of callers added to the object using #addCaller()
955 * or AutoCaller drops to zero. For this reason, it is forbidden to
956 * create instances of this class (or call uninit()) within the
957 * AutoCaller or #addCaller() scope because it is a guaranteed
958 * deadlock.
959 *
960 * @note Never create instances of this class outside uninit() methods and
961 * never pass anything other than |this| as the argument to the
962 * constructor!
963 */
964 class AutoUninitSpan
965 {
966 public:
967
968 AutoUninitSpan(VirtualBoxBaseProto *aObj);
969 ~AutoUninitSpan();
970
971 /** |true| when uninit() is called as a result of init() failure */
972 bool initFailed() { return mInitFailed; }
973
974 /** |true| when uninit() has already been called (so the object is NotReady) */
975 bool uninitDone() { return mUninitDone; }
976
977 private:
978
979 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoUninitSpan)
980 DECLARE_CLS_NEW_DELETE_NOOP(AutoUninitSpan)
981
982 VirtualBoxBaseProto *mObj;
983 bool mInitFailed : 1;
984 bool mUninitDone : 1;
985 };
986
987 /**
988 * Smart class to enclose the state transition Ready->MayUninit->NotReady or
989 * Ready->MayUninit->WillUninit.
990 *
991 * The purpose of this span is to safely check if unintialization is
992 * possible at the given moment and seamlessly perform it if so.
993 *
994 * Instances must be created as a stack-based variable taking |this| pointer
995 * as the argument at the beginning of methods of VirtualBoxBase
996 * subclasses that want to uninitialize the object if a necessary set of
997 * criteria is met and leave it Ready otherwise.
998 *
999 * When this variable is created it automatically places the object to the
1000 * MayUninit state if it is Ready, does nothing but returns |true| in
1001 * response to #alreadyInProgress() if it is already in MayUninit, or
1002 * returns a failure in response to #rc() in any other case. The example
1003 * below shows how the user must react in latter two cases.
1004 *
1005 * When this variable goes out of scope (i.e. gets destroyed), it places the
1006 * object back to Ready state unless #acceptUninit() is called in which case
1007 * the object is placed to WillUninit state and uninit() is immediately
1008 * called after that.
1009 *
1010 * A typical usage pattern is:
1011 * <code>
1012 * void Component::uninit()
1013 * {
1014 * AutoMayUninitSpan mayUninitSpan (this);
1015 * if (FAILED(mayUninitSpan.rc())) return mayUninitSpan.rc();
1016 * if (mayUninitSpan.alreadyInProgress())
1017 * return S_OK;
1018 * ...
1019 * if (FAILED (rc))
1020 * return rc; // will go back to Ready
1021 * ...
1022 * if (SUCCEEDED (rc))
1023 * mayUninitSpan.acceptUninit(); // will call uninit()
1024 * return rc;
1025 * }
1026 * </code>
1027 *
1028 * @note The constructor of this class blocks the current thread execution
1029 * until the number of callers added to the object using #addCaller()
1030 * or AutoCaller drops to zero. For this reason, it is forbidden to
1031 * create instances of this class (or call uninit()) within the
1032 * AutoCaller or #addCaller() scope because it is a guaranteed
1033 * deadlock.
1034 */
1035 class AutoMayUninitSpan
1036 {
1037 public:
1038
1039 AutoMayUninitSpan(VirtualBoxBaseProto *aObj);
1040 ~AutoMayUninitSpan();
1041
1042 /**
1043 * Returns a failure if the AutoMayUninitSpan variable was constructed
1044 * at an improper time. If there is a failure, do nothing but return
1045 * it to the caller.
1046 */
1047 HRESULT rc() { return mRC; }
1048
1049 /**
1050 * Returns |true| if AutoMayUninitSpan is already in progress on some
1051 * other thread. If it's the case, do nothing but return S_OK to
1052 * the caller.
1053 */
1054 bool alreadyInProgress() { return mAlreadyInProgress; }
1055
1056 /*
1057 * Accepts uninitialization and causes the destructor to go to
1058 * WillUninit state and call uninit() afterwards.
1059 */
1060 void acceptUninit() { mAcceptUninit = true; }
1061
1062 private:
1063
1064 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoMayUninitSpan)
1065 DECLARE_CLS_NEW_DELETE_NOOP(AutoMayUninitSpan)
1066
1067 VirtualBoxBaseProto *mObj;
1068
1069 HRESULT mRC;
1070 bool mAlreadyInProgress : 1;
1071 bool mAcceptUninit : 1;
1072 };
1073
1074 /**
1075 * Returns a lock handle used to protect the primary state fields (used by
1076 * #addCaller(), AutoInitSpan, AutoUninitSpan, etc.). Only intended to be
1077 * used for similar purposes in subclasses. WARNING: NO any other locks may
1078 * be requested while holding this lock!
1079 */
1080 WriteLockHandle *stateLockHandle() { return &mStateLock; }
1081
1082private:
1083
1084 void setState(State aState)
1085 {
1086 Assert(mState != aState);
1087 mState = aState;
1088 mStateChangeThread = RTThreadSelf();
1089 }
1090
1091 /** Primary state of this object */
1092 State mState;
1093 /** Thread that caused the last state change */
1094 RTTHREAD mStateChangeThread;
1095 /** Total number of active calls to this object */
1096 unsigned mCallers;
1097 /** Posted when the number of callers drops to zero */
1098 RTSEMEVENT mZeroCallersSem;
1099 /** Posted when the object goes from InInit/InUninit to some other state */
1100 RTSEMEVENTMULTI mInitUninitSem;
1101 /** Number of threads waiting for mInitUninitDoneSem */
1102 unsigned mInitUninitWaiters;
1103
1104 /** Protects access to state related data members */
1105 WriteLockHandle mStateLock;
1106
1107 /** User-level object lock for subclasses */
1108 mutable RWLockHandle *mObjectLock;
1109};
1110
1111////////////////////////////////////////////////////////////////////////////////
1112
1113/**
1114 * This macro adds the error info support to methods of the VirtualBoxBase
1115 * class (by overriding them). Place it to the public section of the
1116 * VirtualBoxBase subclass and the following methods will set the extended
1117 * error info in case of failure instead of just returning the result code:
1118 *
1119 * <ul>
1120 * <li>VirtualBoxBase::addCaller()
1121 * </ul>
1122 *
1123 * @note The given VirtualBoxBase subclass must also inherit from both
1124 * VirtualBoxSupportErrorInfoImpl and VirtualBoxSupportTranslation templates!
1125 *
1126 * @param C VirtualBoxBase subclass to add the error info support to
1127 */
1128#define VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(C) \
1129 virtual HRESULT addCaller(VirtualBoxBaseProto::State *aState = NULL, \
1130 bool aLimited = false) \
1131 { \
1132 VirtualBoxBaseProto::State protoState; \
1133 HRESULT rc = VirtualBoxBaseProto::addCaller(&protoState, aLimited); \
1134 if (FAILED(rc)) \
1135 { \
1136 if (protoState == VirtualBoxBaseProto::Limited) \
1137 rc = setError(rc, tr("The object functionality is limited")); \
1138 else \
1139 rc = setError(rc, tr("The object is not ready")); \
1140 } \
1141 if (aState) \
1142 *aState = protoState; \
1143 return rc; \
1144 } \
1145
1146////////////////////////////////////////////////////////////////////////////////
1147
1148class ATL_NO_VTABLE VirtualBoxBase
1149 : virtual public VirtualBoxBaseProto,
1150 public CComObjectRootEx<CComMultiThreadModel>
1151{
1152
1153public:
1154 VirtualBoxBase()
1155 {}
1156
1157 virtual ~VirtualBoxBase()
1158 {}
1159
1160 /**
1161 * Virtual unintialization method. Called during parent object's
1162 * uninitialization, if the given subclass instance is a dependent child of
1163 * a class derived from VirtualBoxBaseWithChildren (@sa
1164 * VirtualBoxBaseWithChildren::addDependentChild). In this case, this
1165 * method's implementation must call setReady (false),
1166 */
1167 virtual void uninit()
1168 {}
1169
1170 static const char *translate(const char *context, const char *sourceText,
1171 const char *comment = 0);
1172};
1173
1174////////////////////////////////////////////////////////////////////////////////
1175
1176/** Helper for VirtualBoxSupportTranslation. */
1177class VirtualBoxSupportTranslationBase
1178{
1179protected:
1180 static bool cutClassNameFrom__PRETTY_FUNCTION__(char *aPrettyFunctionName);
1181};
1182
1183/**
1184 * The VirtualBoxSupportTranslation template implements the NLS string
1185 * translation support for the given class.
1186 *
1187 * Translation support is provided by the static #tr() function. This function,
1188 * given a string in UTF-8 encoding, looks up for a translation of the given
1189 * string by calling the VirtualBoxBase::translate() global function which
1190 * receives the name of the enclosing class ("context of translation") as the
1191 * additional argument and returns a translated string based on the currently
1192 * active language.
1193 *
1194 * @param C Class that needs to support the string translation.
1195 *
1196 * @note Every class that wants to use the #tr() function in its own methods
1197 * must inherit from this template, regardless of whether its base class
1198 * (if any) inherits from it or not. Otherwise, the translation service
1199 * will not work correctly. However, the declaration of the derived
1200 * class must contain
1201 * the <tt>COM_SUPPORTTRANSLATION_OVERRIDE (<ClassName>)</tt> macro if one
1202 * of its base classes also inherits from this template (to resolve the
1203 * ambiguity of the #tr() function).
1204 */
1205template<class C>
1206class VirtualBoxSupportTranslation : virtual protected VirtualBoxSupportTranslationBase
1207{
1208public:
1209
1210 /**
1211 * Translates the given text string by calling VirtualBoxBase::translate()
1212 * and passing the name of the C class as the first argument ("context of
1213 * translation") See VirtualBoxBase::translate() for more info.
1214 *
1215 * @param aSourceText String to translate.
1216 * @param aComment Comment to the string to resolve possible
1217 * ambiguities (NULL means no comment).
1218 *
1219 * @return Translated version of the source string in UTF-8 encoding, or
1220 * the source string itself if the translation is not found in the
1221 * specified context.
1222 */
1223 inline static const char *tr(const char *aSourceText,
1224 const char *aComment = NULL)
1225 {
1226 return VirtualBoxBase::translate(className(), aSourceText, aComment);
1227 }
1228
1229protected:
1230
1231 static const char *className()
1232 {
1233 static char fn[sizeof(__PRETTY_FUNCTION__) + 1];
1234 if (!sClassName)
1235 {
1236 strcpy(fn, __PRETTY_FUNCTION__);
1237 cutClassNameFrom__PRETTY_FUNCTION__(fn);
1238 sClassName = fn;
1239 }
1240 return sClassName;
1241 }
1242
1243private:
1244
1245 static const char *sClassName;
1246};
1247
1248template<class C>
1249const char *VirtualBoxSupportTranslation<C>::sClassName = NULL;
1250
1251/**
1252 * This macro must be invoked inside the public section of the declaration of
1253 * the class inherited from the VirtualBoxSupportTranslation template in case
1254 * if one of its other base classes also inherits from that template. This is
1255 * necessary to resolve the ambiguity of the #tr() function.
1256 *
1257 * @param C Class that inherits the VirtualBoxSupportTranslation template
1258 * more than once (through its other base clases).
1259 */
1260#define VIRTUALBOXSUPPORTTRANSLATION_OVERRIDE(C) \
1261 inline static const char *tr(const char *aSourceText, \
1262 const char *aComment = NULL) \
1263 { \
1264 return VirtualBoxSupportTranslation<C>::tr(aSourceText, aComment); \
1265 }
1266
1267/**
1268 * Dummy macro that is used to shut down Qt's lupdate tool warnings in some
1269 * situations. This macro needs to be present inside (better at the very
1270 * beginning) of the declaration of the class that inherits from
1271 * VirtualBoxSupportTranslation template, to make lupdate happy.
1272 */
1273#define Q_OBJECT
1274
1275////////////////////////////////////////////////////////////////////////////////
1276
1277/**
1278 * Helper for the VirtualBoxSupportErrorInfoImpl template.
1279 */
1280/// @todo switch to com::SupportErrorInfo* and remove
1281class VirtualBoxSupportErrorInfoImplBase
1282{
1283 static HRESULT setErrorInternal(HRESULT aResultCode, const GUID &aIID,
1284 const Bstr &aComponent, const Bstr &aText,
1285 bool aWarning, bool aLogIt);
1286
1287protected:
1288
1289 /**
1290 * The MultiResult class is a com::FWResult enhancement that also acts as a
1291 * switch to turn on multi-error mode for #setError() or #setWarning()
1292 * calls.
1293 *
1294 * When an instance of this class is created, multi-error mode is turned on
1295 * for the current thread and the turn-on counter is increased by one. In
1296 * multi-error mode, a call to #setError() or #setWarning() does not
1297 * overwrite the current error or warning info object possibly set on the
1298 * current thread by other method calls, but instead it stores this old
1299 * object in the IVirtualBoxErrorInfo::next attribute of the new error
1300 * object being set.
1301 *
1302 * This way, error/warning objects are stacked together and form a chain of
1303 * errors where the most recent error is the first one retrieved by the
1304 * calling party, the preceding error is what the
1305 * IVirtualBoxErrorInfo::next attribute of the first error points to, and so
1306 * on, up to the first error or warning occurred which is the last in the
1307 * chain. See IVirtualBoxErrorInfo documentation for more info.
1308 *
1309 * When the instance of the MultiResult class goes out of scope and gets
1310 * destroyed, it automatically decreases the turn-on counter by one. If
1311 * the counter drops to zero, multi-error mode for the current thread is
1312 * turned off and the thread switches back to single-error mode where every
1313 * next error or warning object overwrites the previous one.
1314 *
1315 * Note that the caller of a COM method uses a non-S_OK result code to
1316 * decide if the method has returned an error (negative codes) or a warning
1317 * (positive non-zero codes) and will query extended error info only in
1318 * these two cases. However, since multi-error mode implies that the method
1319 * doesn't return control return to the caller immediately after the first
1320 * error or warning but continues its execution, the functionality provided
1321 * by the base com::FWResult class becomes very useful because it allows to
1322 * preserve the error or the warning result code even if it is later assigned
1323 * a S_OK value multiple times. See com::FWResult for details.
1324 *
1325 * Here is the typical usage pattern:
1326 * <code>
1327
1328 HRESULT Bar::method()
1329 {
1330 // assume multi-errors are turned off here...
1331
1332 if (something)
1333 {
1334 // Turn on multi-error mode and make sure severity is preserved
1335 MultiResult rc = foo->method1();
1336
1337 // return on fatal error, but continue on warning or on success
1338 if (FAILED(rc)) return rc;
1339
1340 rc = foo->method2();
1341 // no matter what result, stack it and continue
1342
1343 // ...
1344
1345 // return the last worst result code (it will be preserved even if
1346 // foo->method2() returns S_OK.
1347 return rc;
1348 }
1349
1350 // multi-errors are turned off here again...
1351
1352 return S_OK;
1353 }
1354
1355 * </code>
1356 *
1357 *
1358 * @note This class is intended to be instantiated on the stack, therefore
1359 * You cannot create them using new(). Although it is possible to copy
1360 * instances of MultiResult or return them by value, please never do
1361 * that as it is breaks the class semantics (and will assert).
1362 */
1363 class MultiResult : public com::FWResult
1364 {
1365 public:
1366
1367 /**
1368 * @copydoc com::FWResult::FWResult().
1369 */
1370 MultiResult(HRESULT aRC = E_FAIL) : FWResult(aRC) { init(); }
1371
1372 MultiResult(const MultiResult &aThat) : FWResult(aThat)
1373 {
1374 /* We need this copy constructor only for GCC that wants to have
1375 * it in case of expressions like |MultiResult rc = E_FAIL;|. But
1376 * we assert since the optimizer should actually avoid the
1377 * temporary and call the other constructor directly instead. */
1378 AssertFailed();
1379 init();
1380 }
1381
1382 ~MultiResult();
1383
1384 MultiResult &operator=(HRESULT aRC)
1385 {
1386 com::FWResult::operator=(aRC);
1387 return *this;
1388 }
1389
1390 MultiResult &operator=(const MultiResult &aThat)
1391 {
1392 /* We need this copy constructor only for GCC that wants to have
1393 * it in case of expressions like |MultiResult rc = E_FAIL;|. But
1394 * we assert since the optimizer should actually avoid the
1395 * temporary and call the other constructor directly instead. */
1396 AssertFailed();
1397 com::FWResult::operator=(aThat);
1398 return *this;
1399 }
1400
1401 private:
1402
1403 DECLARE_CLS_NEW_DELETE_NOOP(MultiResult)
1404
1405 void init();
1406
1407 static RTTLS sCounter;
1408
1409 friend class VirtualBoxSupportErrorInfoImplBase;
1410 };
1411
1412 static HRESULT setError(HRESULT aResultCode, const GUID &aIID,
1413 const Bstr &aComponent,
1414 const Bstr &aText,
1415 bool aLogIt = true)
1416 {
1417 return setErrorInternal(aResultCode, aIID, aComponent, aText,
1418 false /* aWarning */, aLogIt);
1419 }
1420
1421 static HRESULT setWarning(HRESULT aResultCode, const GUID &aIID,
1422 const Bstr &aComponent,
1423 const Bstr &aText)
1424 {
1425 return setErrorInternal(aResultCode, aIID, aComponent, aText,
1426 true /* aWarning */, true /* aLogIt */);
1427 }
1428
1429 static HRESULT setError(HRESULT aResultCode, const GUID &aIID,
1430 const Bstr &aComponent,
1431 const char *aText, va_list aArgs, bool aLogIt = true)
1432 {
1433 return setErrorInternal(aResultCode, aIID, aComponent,
1434 Utf8StrFmtVA (aText, aArgs),
1435 false /* aWarning */, aLogIt);
1436 }
1437
1438 static HRESULT setWarning(HRESULT aResultCode, const GUID &aIID,
1439 const Bstr &aComponent,
1440 const char *aText, va_list aArgs)
1441 {
1442 return setErrorInternal(aResultCode, aIID, aComponent,
1443 Utf8StrFmtVA (aText, aArgs),
1444 true /* aWarning */, true /* aLogIt */);
1445 }
1446};
1447
1448/**
1449 * This template implements ISupportErrorInfo for the given component class
1450 * and provides the #setError() method to conveniently set the error information
1451 * from within interface methods' implementations.
1452 *
1453 * On Windows, the template argument must define a COM interface map using
1454 * BEGIN_COM_MAP / END_COM_MAP macros and this map must contain a
1455 * COM_INTERFACE_ENTRY(ISupportErrorInfo) definition. All interface entries
1456 * that follow it will be considered to support IErrorInfo, i.e. the
1457 * InterfaceSupportsErrorInfo() implementation will return S_OK for the
1458 * corresponding IID.
1459 *
1460 * On all platforms, the template argument must also define the following
1461 * method: |public static const wchar_t *C::getComponentName()|. See
1462 * #setError (HRESULT, const char *, ...) for a description on how it is
1463 * used.
1464 *
1465 * @param C
1466 * component class that implements one or more COM interfaces
1467 * @param I
1468 * default interface for the component. This interface's IID is used
1469 * by the shortest form of #setError, for convenience.
1470 */
1471/// @todo switch to com::SupportErrorInfo* and remove
1472template<class C, class I>
1473class ATL_NO_VTABLE VirtualBoxSupportErrorInfoImpl
1474 : protected VirtualBoxSupportErrorInfoImplBase
1475#if !defined (VBOX_WITH_XPCOM)
1476 , public ISupportErrorInfo
1477#else
1478#endif
1479{
1480public:
1481
1482#if !defined (VBOX_WITH_XPCOM)
1483 STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid)
1484 {
1485 const _ATL_INTMAP_ENTRY* pEntries = C::_GetEntries();
1486 Assert(pEntries);
1487 if (!pEntries)
1488 return S_FALSE;
1489
1490 BOOL bSupports = FALSE;
1491 BOOL bISupportErrorInfoFound = FALSE;
1492
1493 while (pEntries->pFunc != NULL && !bSupports)
1494 {
1495 if (!bISupportErrorInfoFound)
1496 {
1497 // skip the com map entries until ISupportErrorInfo is found
1498 bISupportErrorInfoFound =
1499 InlineIsEqualGUID(*(pEntries->piid), IID_ISupportErrorInfo);
1500 }
1501 else
1502 {
1503 // look for the requested interface in the rest of the com map
1504 bSupports = InlineIsEqualGUID(*(pEntries->piid), riid);
1505 }
1506 pEntries++;
1507 }
1508
1509 Assert(bISupportErrorInfoFound);
1510
1511 return bSupports ? S_OK : S_FALSE;
1512 }
1513#endif // !defined (VBOX_WITH_XPCOM)
1514
1515protected:
1516
1517 /**
1518 * Sets the error information for the current thread.
1519 * This information can be retrieved by a caller of an interface method
1520 * using IErrorInfo on Windows or nsIException on Linux, or the cross-platform
1521 * IVirtualBoxErrorInfo interface that provides extended error info (only
1522 * for components from the VirtualBox COM library). Alternatively, the
1523 * platform-independent class com::ErrorInfo (defined in VBox[XP]COM.lib)
1524 * can be used to retrieve error info in a convenient way.
1525 *
1526 * It is assumed that the interface method that uses this function returns
1527 * an unsuccessful result code to the caller (otherwise, there is no reason
1528 * for the caller to try to retrieve error info after method invocation).
1529 *
1530 * Here is a table of correspondence between this method's arguments
1531 * and IErrorInfo/nsIException/IVirtualBoxErrorInfo attributes/methods:
1532 *
1533 * argument IErrorInfo nsIException IVirtualBoxErrorInfo
1534 * ----------------------------------------------------------------
1535 * resultCode -- result resultCode
1536 * iid GetGUID -- interfaceID
1537 * component GetSource -- component
1538 * text GetDescription message text
1539 *
1540 * This method is rarely needs to be used though. There are more convenient
1541 * overloaded versions, that automatically substitute some arguments
1542 * taking their values from the template parameters. See
1543 * #setError (HRESULT, const char *, ...) for an example.
1544 *
1545 * @param aResultCode result (error) code, must not be S_OK
1546 * @param aIID IID of the interface that defines the error
1547 * @param aComponent name of the component that generates the error
1548 * @param aText error message (must not be null), an RTStrPrintf-like
1549 * format string in UTF-8 encoding
1550 * @param ... list of arguments for the format string
1551 *
1552 * @return
1553 * the error argument, for convenience, If an error occurs while
1554 * creating error info itself, that error is returned instead of the
1555 * error argument.
1556 */
1557 static HRESULT setError(HRESULT aResultCode, const GUID &aIID,
1558 const wchar_t *aComponent,
1559 const char *aText, ...)
1560 {
1561 va_list args;
1562 va_start(args, aText);
1563 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError(
1564 aResultCode, aIID, aComponent, aText, args, true /* aLogIt */);
1565 va_end(args);
1566 return rc;
1567 }
1568
1569 /**
1570 * This method is the same as #setError() except that it makes sure @a
1571 * aResultCode doesn't have the error severity bit (31) set when passed
1572 * down to the created IVirtualBoxErrorInfo object.
1573 *
1574 * The error severity bit is always cleared by this call, thereof you can
1575 * use ordinary E_XXX result code constants, for convenience. However, this
1576 * behavior may be non-standard on some COM platforms.
1577 */
1578 static HRESULT setWarning(HRESULT aResultCode, const GUID &aIID,
1579 const wchar_t *aComponent,
1580 const char *aText, ...)
1581 {
1582 va_list args;
1583 va_start(args, aText);
1584 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setWarning(
1585 aResultCode, aIID, aComponent, aText, args);
1586 va_end(args);
1587 return rc;
1588 }
1589
1590 /**
1591 * Sets the error information for the current thread.
1592 * A convenience method that automatically sets the default interface
1593 * ID (taken from the I template argument) and the component name
1594 * (a value of C::getComponentName()).
1595 *
1596 * See #setError (HRESULT, const GUID &, const wchar_t *, const char *text, ...)
1597 * for details.
1598 *
1599 * This method is the most common (and convenient) way to set error
1600 * information from within interface methods. A typical pattern of usage
1601 * is looks like this:
1602 *
1603 * <code>
1604 * return setError (E_FAIL, "Terrible Error");
1605 * </code>
1606 * or
1607 * <code>
1608 * HRESULT rc = setError (E_FAIL, "Terrible Error");
1609 * ...
1610 * return rc;
1611 * </code>
1612 */
1613 static HRESULT setError(HRESULT aResultCode, const char *aText, ...)
1614 {
1615 va_list args;
1616 va_start(args, aText);
1617 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError(
1618 aResultCode, COM_IIDOF(I), C::getComponentName(), aText, args, true /* aLogIt */);
1619 va_end(args);
1620 return rc;
1621 }
1622
1623 /**
1624 * This method is the same as #setError() except that it makes sure @a
1625 * aResultCode doesn't have the error severity bit (31) set when passed
1626 * down to the created IVirtualBoxErrorInfo object.
1627 *
1628 * The error severity bit is always cleared by this call, thereof you can
1629 * use ordinary E_XXX result code constants, for convenience. However, this
1630 * behavior may be non-standard on some COM platforms.
1631 */
1632 static HRESULT setWarning(HRESULT aResultCode, const char *aText, ...)
1633 {
1634 va_list args;
1635 va_start(args, aText);
1636 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setWarning(
1637 aResultCode, COM_IIDOF(I), C::getComponentName(), aText, args);
1638 va_end(args);
1639 return rc;
1640 }
1641
1642 /**
1643 * Sets the error information for the current thread, va_list variant.
1644 * A convenience method that automatically sets the default interface
1645 * ID (taken from the I template argument) and the component name
1646 * (a value of C::getComponentName()).
1647 *
1648 * See #setError (HRESULT, const GUID &, const wchar_t *, const char *text, ...)
1649 * and #setError (HRESULT, const char *, ...) for details.
1650 */
1651 static HRESULT setErrorV(HRESULT aResultCode, const char *aText,
1652 va_list aArgs)
1653 {
1654 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError(
1655 aResultCode, COM_IIDOF(I), C::getComponentName(), aText, aArgs, true /* aLogIt */);
1656 return rc;
1657 }
1658
1659 /**
1660 * This method is the same as #setErrorV() except that it makes sure @a
1661 * aResultCode doesn't have the error severity bit (31) set when passed
1662 * down to the created IVirtualBoxErrorInfo object.
1663 *
1664 * The error severity bit is always cleared by this call, thereof you can
1665 * use ordinary E_XXX result code constants, for convenience. However, this
1666 * behavior may be non-standard on some COM platforms.
1667 */
1668 static HRESULT setWarningV(HRESULT aResultCode, const char *aText,
1669 va_list aArgs)
1670 {
1671 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setWarning(
1672 aResultCode, COM_IIDOF(I), C::getComponentName(), aText, aArgs);
1673 return rc;
1674 }
1675
1676 /**
1677 * Sets the error information for the current thread, BStr variant.
1678 * A convenience method that automatically sets the default interface
1679 * ID (taken from the I template argument) and the component name
1680 * (a value of C::getComponentName()).
1681 *
1682 * This method is preferred if you have a ready (translated and formatted)
1683 * Bstr string, because it omits an extra conversion Utf8Str -> Bstr.
1684 *
1685 * See #setError (HRESULT, const GUID &, const wchar_t *, const char *text, ...)
1686 * and #setError (HRESULT, const char *, ...) for details.
1687 */
1688 static HRESULT setErrorBstr(HRESULT aResultCode, const Bstr &aText)
1689 {
1690 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError(
1691 aResultCode, COM_IIDOF(I), C::getComponentName(), aText, true /* aLogIt */);
1692 return rc;
1693 }
1694
1695 /**
1696 * This method is the same as #setErrorBstr() except that it makes sure @a
1697 * aResultCode doesn't have the error severity bit (31) set when passed
1698 * down to the created IVirtualBoxErrorInfo object.
1699 *
1700 * The error severity bit is always cleared by this call, thereof you can
1701 * use ordinary E_XXX result code constants, for convenience. However, this
1702 * behavior may be non-standard on some COM platforms.
1703 */
1704 static HRESULT setWarningBstr(HRESULT aResultCode, const Bstr &aText)
1705 {
1706 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setWarning(
1707 aResultCode, COM_IIDOF(I), C::getComponentName(), aText);
1708 return rc;
1709 }
1710
1711 /**
1712 * Sets the error information for the current thread.
1713 * A convenience method that automatically sets the component name
1714 * (a value of C::getComponentName()), but allows to specify the interface
1715 * id manually.
1716 *
1717 * See #setError (HRESULT, const GUID &, const wchar_t *, const char *text, ...)
1718 * for details.
1719 */
1720 static HRESULT setError(HRESULT aResultCode, const GUID &aIID,
1721 const char *aText, ...)
1722 {
1723 va_list args;
1724 va_start(args, aText);
1725 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError(
1726 aResultCode, aIID, C::getComponentName(), aText, args, true /* aLogIt */);
1727 va_end(args);
1728 return rc;
1729 }
1730
1731 /**
1732 * This method is the same as #setError() except that it makes sure @a
1733 * aResultCode doesn't have the error severity bit (31) set when passed
1734 * down to the created IVirtualBoxErrorInfo object.
1735 *
1736 * The error severity bit is always cleared by this call, thereof you can
1737 * use ordinary E_XXX result code constants, for convenience. However, this
1738 * behavior may be non-standard on some COM platforms.
1739 */
1740 static HRESULT setWarning(HRESULT aResultCode, const GUID &aIID,
1741 const char *aText, ...)
1742 {
1743 va_list args;
1744 va_start(args, aText);
1745 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setWarning(
1746 aResultCode, aIID, C::getComponentName(), aText, args);
1747 va_end(args);
1748 return rc;
1749 }
1750
1751 /**
1752 * Sets the error information for the current thread but doesn't put
1753 * anything in the release log. This is very useful for avoiding
1754 * harmless error from causing confusion.
1755 *
1756 * It is otherwise identical to #setError (HRESULT, const char *text, ...).
1757 */
1758 static HRESULT setErrorNoLog(HRESULT aResultCode, const char *aText, ...)
1759 {
1760 va_list args;
1761 va_start(args, aText);
1762 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError(
1763 aResultCode, COM_IIDOF(I), C::getComponentName(), aText, args, false /* aLogIt */);
1764 va_end(args);
1765 return rc;
1766 }
1767
1768private:
1769
1770};
1771
1772
1773/**
1774 * Base class to track VirtualBoxBaseNEXT chlidren of the component.
1775 *
1776 * This class is a preferrable VirtualBoxBase replacement for components that
1777 * operate with collections of child components. It gives two useful
1778 * possibilities:
1779 *
1780 * <ol><li>
1781 * Given an IUnknown instance, it's possible to quickly determine
1782 * whether this instance represents a child object that belongs to the
1783 * given component, and if so, get a valid VirtualBoxBase pointer to the
1784 * child object. The returned pointer can be then safely casted to the
1785 * actual class of the child object (to get access to its "internal"
1786 * non-interface methods) provided that no other child components implement
1787 * the same original COM interface IUnknown is queried from.
1788 * </li><li>
1789 * When the parent object uninitializes itself, it can easily unintialize
1790 * all its VirtualBoxBase derived children (using their
1791 * VirtualBoxBase::uninit() implementations). This is done simply by
1792 * calling the #uninitDependentChildren() method.
1793 * </li></ol>
1794 *
1795 * In order to let the above work, the following must be done:
1796 * <ol><li>
1797 * When a child object is initialized, it calls #addDependentChild() of
1798 * its parent to register itself within the list of dependent children.
1799 * </li><li>
1800 * When the child object it is uninitialized, it calls
1801 * #removeDependentChild() to unregister itself.
1802 * </li></ol>
1803 *
1804 * Note that if the parent object does not call #uninitDependentChildren() when
1805 * it gets uninitialized, it must call uninit() methods of individual children
1806 * manually to disconnect them; a failure to do so will cause crashes in these
1807 * methods when children get destroyed. The same applies to children not calling
1808 * #removeDependentChild() when getting destroyed.
1809 *
1810 * Note that children added by #addDependentChild() are <b>weakly</b> referenced
1811 * (i.e. AddRef() is not called), so when a child object is deleted externally
1812 * (because it's reference count goes to zero), it will automatically remove
1813 * itself from the map of dependent children provided that it follows the rules
1814 * described here.
1815 *
1816 * Access to the child list is serialized using the #childrenLock() lock handle
1817 * (which defaults to the general object lock handle (see
1818 * VirtualBoxBase::lockHandle()). This lock is used by all add/remove methods of
1819 * this class so be aware of the need to preserve the {parent, child} lock order
1820 * when calling these methods.
1821 *
1822 * Read individual method descriptions to get further information.
1823 *
1824 * @todo This is a VirtualBoxBaseWithChildren equivalent that uses the
1825 * VirtualBoxBaseNEXT implementation. Will completely supersede
1826 * VirtualBoxBaseWithChildren after the old VirtualBoxBase implementation
1827 * has gone.
1828 */
1829class VirtualBoxBaseWithChildrenNEXT : public VirtualBoxBase
1830{
1831public:
1832
1833 VirtualBoxBaseWithChildrenNEXT()
1834 {}
1835
1836 virtual ~VirtualBoxBaseWithChildrenNEXT()
1837 {}
1838
1839 /**
1840 * Lock handle to use when adding/removing child objects from the list of
1841 * children. It is guaranteed that no any other lock is requested in methods
1842 * of this class while holding this lock.
1843 *
1844 * @warning By default, this simply returns the general object's lock handle
1845 * (see VirtualBoxBase::lockHandle()) which is sufficient for most
1846 * cases.
1847 */
1848 virtual RWLockHandle *childrenLock() { return lockHandle(); }
1849
1850 /**
1851 * Adds the given child to the list of dependent children.
1852 *
1853 * Usually gets called from the child's init() method.
1854 *
1855 * @note @a aChild (unless it is in InInit state) must be protected by
1856 * VirtualBoxBase::AutoCaller to make sure it is not uninitialized on
1857 * another thread during this method's call.
1858 *
1859 * @note When #childrenLock() is not overloaded (returns the general object
1860 * lock) and this method is called from under the child's read or
1861 * write lock, make sure the {parent, child} locking order is
1862 * preserved by locking the callee (this object) for writing before
1863 * the child's lock.
1864 *
1865 * @param aChild Child object to add (must inherit VirtualBoxBase AND
1866 * implement some interface).
1867 *
1868 * @note Locks #childrenLock() for writing.
1869 */
1870 template<class C>
1871 void addDependentChild(C *aChild)
1872 {
1873 AssertReturnVoid(aChild != NULL);
1874 doAddDependentChild(ComPtr<IUnknown>(aChild), aChild);
1875 }
1876
1877 /**
1878 * Equivalent to template <class C> void addDependentChild (C *aChild)
1879 * but takes a ComObjPtr<C> argument.
1880 */
1881 template<class C>
1882 void addDependentChild(const ComObjPtr<C> &aChild)
1883 {
1884 AssertReturnVoid(!aChild.isNull());
1885 doAddDependentChild(ComPtr<IUnknown>(static_cast<C *>(aChild)), aChild);
1886 }
1887
1888 /**
1889 * Removes the given child from the list of dependent children.
1890 *
1891 * Usually gets called from the child's uninit() method.
1892 *
1893 * Keep in mind that the called (parent) object may be no longer available
1894 * (i.e. may be deleted deleted) after this method returns, so you must not
1895 * call any other parent's methods after that!
1896 *
1897 * @note Locks #childrenLock() for writing.
1898 *
1899 * @note @a aChild (unless it is in InUninit state) must be protected by
1900 * VirtualBoxBase::AutoCaller to make sure it is not uninitialized on
1901 * another thread during this method's call.
1902 *
1903 * @note When #childrenLock() is not overloaded (returns the general object
1904 * lock) and this method is called from under the child's read or
1905 * write lock, make sure the {parent, child} locking order is
1906 * preserved by locking the callee (this object) for writing before
1907 * the child's lock. This is irrelevant when the method is called from
1908 * under this object's VirtualBoxBaseProto::AutoUninitSpan (i.e. in
1909 * InUninit state) since in this case no locking is done.
1910 *
1911 * @param aChild Child object to remove.
1912 *
1913 * @note Locks #childrenLock() for writing.
1914 */
1915 template<class C>
1916 void removeDependentChild(C *aChild)
1917 {
1918 AssertReturnVoid(aChild != NULL);
1919 doRemoveDependentChild(ComPtr<IUnknown>(aChild));
1920 }
1921
1922 /**
1923 * Equivalent to template <class C> void removeDependentChild (C *aChild)
1924 * but takes a ComObjPtr<C> argument.
1925 */
1926 template<class C>
1927 void removeDependentChild(const ComObjPtr<C> &aChild)
1928 {
1929 AssertReturnVoid(!aChild.isNull());
1930 doRemoveDependentChild(ComPtr<IUnknown>(static_cast<C *>(aChild)));
1931 }
1932
1933protected:
1934
1935 void uninitDependentChildren();
1936
1937 VirtualBoxBase *getDependentChild(const ComPtr<IUnknown> &aUnk);
1938
1939private:
1940 void doAddDependentChild(IUnknown *aUnk, VirtualBoxBase *aChild);
1941 void doRemoveDependentChild(IUnknown *aUnk);
1942
1943 typedef std::map<IUnknown*, VirtualBoxBase*> DependentChildren;
1944 DependentChildren mDependentChildren;
1945};
1946
1947////////////////////////////////////////////////////////////////////////////////
1948
1949////////////////////////////////////////////////////////////////////////////////
1950
1951
1952/// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
1953/**
1954 * Simple template that manages data structure allocation/deallocation
1955 * and supports data pointer sharing (the instance that shares the pointer is
1956 * not responsible for memory deallocation as opposed to the instance that
1957 * owns it).
1958 */
1959template <class D>
1960class Shareable
1961{
1962public:
1963
1964 Shareable() : mData (NULL), mIsShared(FALSE) {}
1965 ~Shareable() { free(); }
1966
1967 void allocate() { attach(new D); }
1968
1969 virtual void free() {
1970 if (mData) {
1971 if (!mIsShared)
1972 delete mData;
1973 mData = NULL;
1974 mIsShared = false;
1975 }
1976 }
1977
1978 void attach(D *d) {
1979 AssertMsg(d, ("new data must not be NULL"));
1980 if (d && mData != d) {
1981 if (mData && !mIsShared)
1982 delete mData;
1983 mData = d;
1984 mIsShared = false;
1985 }
1986 }
1987
1988 void attach(Shareable &d) {
1989 AssertMsg(
1990 d.mData == mData || !d.mIsShared,
1991 ("new data must not be shared")
1992 );
1993 if (this != &d && !d.mIsShared) {
1994 attach(d.mData);
1995 d.mIsShared = true;
1996 }
1997 }
1998
1999 void share(D *d) {
2000 AssertMsg(d, ("new data must not be NULL"));
2001 if (mData != d) {
2002 if (mData && !mIsShared)
2003 delete mData;
2004 mData = d;
2005 mIsShared = true;
2006 }
2007 }
2008
2009 void share(const Shareable &d) { share(d.mData); }
2010
2011 void attachCopy(const D *d) {
2012 AssertMsg(d, ("data to copy must not be NULL"));
2013 if (d)
2014 attach(new D(*d));
2015 }
2016
2017 void attachCopy(const Shareable &d) {
2018 attachCopy(d.mData);
2019 }
2020
2021 virtual D *detach() {
2022 D *d = mData;
2023 mData = NULL;
2024 mIsShared = false;
2025 return d;
2026 }
2027
2028 D *data() const {
2029 return mData;
2030 }
2031
2032 D *operator->() const {
2033 AssertMsg(mData, ("data must not be NULL"));
2034 return mData;
2035 }
2036
2037 bool isNull() const { return mData == NULL; }
2038 bool operator!() const { return isNull(); }
2039
2040 bool isShared() const { return mIsShared; }
2041
2042protected:
2043
2044 D *mData;
2045 bool mIsShared;
2046};
2047
2048/// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
2049/**
2050 * Simple template that enhances Shareable<> and supports data
2051 * backup/rollback/commit (using the copy constructor of the managed data
2052 * structure).
2053 */
2054template<class D>
2055class Backupable : public Shareable<D>
2056{
2057public:
2058
2059 Backupable() : Shareable<D> (), mBackupData(NULL) {}
2060
2061 void free()
2062 {
2063 AssertMsg(this->mData || !mBackupData, ("backup must be NULL if data is NULL"));
2064 rollback();
2065 Shareable<D>::free();
2066 }
2067
2068 D *detach()
2069 {
2070 AssertMsg(this->mData || !mBackupData, ("backup must be NULL if data is NULL"));
2071 rollback();
2072 return Shareable<D>::detach();
2073 }
2074
2075 void share(const Backupable &d)
2076 {
2077 AssertMsg(!d.isBackedUp(), ("data to share must not be backed up"));
2078 if (!d.isBackedUp())
2079 Shareable<D>::share(d.mData);
2080 }
2081
2082 /**
2083 * Stores the current data pointer in the backup area, allocates new data
2084 * using the copy constructor on current data and makes new data active.
2085 */
2086 void backup()
2087 {
2088 AssertMsg(this->mData, ("data must not be NULL"));
2089 if (this->mData && !mBackupData)
2090 {
2091 D *pNewData = new D(*this->mData);
2092 mBackupData = this->mData;
2093 this->mData = pNewData;
2094 }
2095 }
2096
2097 /**
2098 * Deletes new data created by #backup() and restores previous data pointer
2099 * stored in the backup area, making it active again.
2100 */
2101 void rollback()
2102 {
2103 if (this->mData && mBackupData)
2104 {
2105 delete this->mData;
2106 this->mData = mBackupData;
2107 mBackupData = NULL;
2108 }
2109 }
2110
2111 /**
2112 * Commits current changes by deleting backed up data and clearing up the
2113 * backup area. The new data pointer created by #backup() remains active
2114 * and becomes the only managed pointer.
2115 *
2116 * This method is much faster than #commitCopy() (just a single pointer
2117 * assignment operation), but makes the previous data pointer invalid
2118 * (because it is freed). For this reason, this method must not be
2119 * used if it's possible that data managed by this instance is shared with
2120 * some other Shareable instance. See #commitCopy().
2121 */
2122 void commit()
2123 {
2124 if (this->mData && mBackupData)
2125 {
2126 if (!this->mIsShared)
2127 delete mBackupData;
2128 mBackupData = NULL;
2129 this->mIsShared = false;
2130 }
2131 }
2132
2133 /**
2134 * Commits current changes by assigning new data to the previous data
2135 * pointer stored in the backup area using the assignment operator.
2136 * New data is deleted, the backup area is cleared and the previous data
2137 * pointer becomes active and the only managed pointer.
2138 *
2139 * This method is slower than #commit(), but it keeps the previous data
2140 * pointer valid (i.e. new data is copied to the same memory location).
2141 * For that reason it's safe to use this method on instances that share
2142 * managed data with other Shareable instances.
2143 */
2144 void commitCopy()
2145 {
2146 if (this->mData && mBackupData)
2147 {
2148 *mBackupData = *(this->mData);
2149 delete this->mData;
2150 this->mData = mBackupData;
2151 mBackupData = NULL;
2152 }
2153 }
2154
2155 void assignCopy(const D *pData)
2156 {
2157 AssertMsg(this->mData, ("data must not be NULL"));
2158 AssertMsg(pData, ("data to copy must not be NULL"));
2159 if (this->mData && pData)
2160 {
2161 if (!mBackupData)
2162 {
2163 D *pNewData = new D(*pData);
2164 mBackupData = this->mData;
2165 this->mData = pNewData;
2166 }
2167 else
2168 *this->mData = *pData;
2169 }
2170 }
2171
2172 void assignCopy(const Backupable &d)
2173 {
2174 assignCopy(d.mData);
2175 }
2176
2177 bool isBackedUp() const
2178 {
2179 return mBackupData != NULL;
2180 }
2181
2182 bool hasActualChanges() const
2183 {
2184 AssertMsg(this->mData, ("data must not be NULL"));
2185 return this->mData != NULL && mBackupData != NULL &&
2186 !(*this->mData == *mBackupData);
2187 }
2188
2189 D *backedUpData() const
2190 {
2191 return mBackupData;
2192 }
2193
2194protected:
2195
2196 D *mBackupData;
2197};
2198
2199#endif // !____H_VIRTUALBOXBASEIMPL
2200
Note: See TracBrowser for help on using the repository browser.

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