VirtualBox

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

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

Main: move AutoLock classes to glue

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