VirtualBox

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

Last change on this file since 33595 was 33540, checked in by vboxsync, 14 years ago

*: spelling fixes, thanks Timeless!

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 40.3 KB
Line 
1/** @file
2 * VirtualBox COM base classes definition
3 */
4
5/*
6 * Copyright (C) 2006-2010 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 */
16
17#ifndef ____H_VIRTUALBOXBASEIMPL
18#define ____H_VIRTUALBOXBASEIMPL
19
20#include <iprt/cdefs.h>
21#include <iprt/thread.h>
22
23#include <list>
24#include <map>
25
26#include "VBox/com/AutoLock.h"
27#include "VBox/com/string.h"
28#include "VBox/com/Guid.h"
29
30#include "VBox/com/VirtualBox.h"
31
32// avoid including VBox/settings.h and VBox/xml.h;
33// only declare the classes
34namespace xml
35{
36class File;
37}
38
39using namespace com;
40using namespace util;
41
42class AutoInitSpan;
43class AutoUninitSpan;
44
45class VirtualBox;
46class Machine;
47class Medium;
48class Host;
49typedef std::list< ComObjPtr<Medium> > MediaList;
50
51////////////////////////////////////////////////////////////////////////////////
52//
53// COM helpers
54//
55////////////////////////////////////////////////////////////////////////////////
56
57#if !defined (VBOX_WITH_XPCOM)
58
59#include <atlcom.h>
60
61/* use a special version of the singleton class factory,
62 * see KB811591 in msdn for more info. */
63
64#undef DECLARE_CLASSFACTORY_SINGLETON
65#define DECLARE_CLASSFACTORY_SINGLETON(obj) DECLARE_CLASSFACTORY_EX(CMyComClassFactorySingleton<obj>)
66
67template <class T>
68class CMyComClassFactorySingleton : public CComClassFactory
69{
70public:
71 CMyComClassFactorySingleton() : m_hrCreate(S_OK){}
72 virtual ~CMyComClassFactorySingleton(){}
73 // IClassFactory
74 STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj)
75 {
76 HRESULT hRes = E_POINTER;
77 if (ppvObj != NULL)
78 {
79 *ppvObj = NULL;
80 // Aggregation is not supported in singleton objects.
81 ATLASSERT(pUnkOuter == NULL);
82 if (pUnkOuter != NULL)
83 hRes = CLASS_E_NOAGGREGATION;
84 else
85 {
86 if (m_hrCreate == S_OK && m_spObj == NULL)
87 {
88 Lock();
89 __try
90 {
91 // Fix: The following If statement was moved inside the __try statement.
92 // Did another thread arrive here first?
93 if (m_hrCreate == S_OK && m_spObj == NULL)
94 {
95 // lock the module to indicate activity
96 // (necessary for the monitor shutdown thread to correctly
97 // terminate the module in case when CreateInstance() fails)
98 _pAtlModule->Lock();
99 CComObjectCached<T> *p;
100 m_hrCreate = CComObjectCached<T>::CreateInstance(&p);
101 if (SUCCEEDED(m_hrCreate))
102 {
103 m_hrCreate = p->QueryInterface(IID_IUnknown, (void**)&m_spObj);
104 if (FAILED(m_hrCreate))
105 {
106 delete p;
107 }
108 }
109 _pAtlModule->Unlock();
110 }
111 }
112 __finally
113 {
114 Unlock();
115 }
116 }
117 if (m_hrCreate == S_OK)
118 {
119 hRes = m_spObj->QueryInterface(riid, ppvObj);
120 }
121 else
122 {
123 hRes = m_hrCreate;
124 }
125 }
126 }
127 return hRes;
128 }
129 HRESULT m_hrCreate;
130 CComPtr<IUnknown> m_spObj;
131};
132
133#endif /* !defined (VBOX_WITH_XPCOM) */
134
135////////////////////////////////////////////////////////////////////////////////
136//
137// Macros
138//
139////////////////////////////////////////////////////////////////////////////////
140
141/**
142 * Special version of the Assert macro to be used within VirtualBoxBase
143 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
144 *
145 * In the debug build, this macro is equivalent to Assert.
146 * In the release build, this macro uses |setError(E_FAIL, ...)| to set the
147 * error info from the asserted expression.
148 *
149 * @see VirtualBoxSupportErrorInfoImpl::setError
150 *
151 * @param expr Expression which should be true.
152 */
153#if defined (DEBUG)
154#define ComAssert(expr) Assert(expr)
155#else
156#define ComAssert(expr) \
157 do { \
158 if (RT_UNLIKELY(!(expr))) \
159 setError(E_FAIL, \
160 "Assertion failed: [%s] at '%s' (%d) in %s.\nPlease contact the product vendor!", \
161 #expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
162 } while (0)
163#endif
164
165/**
166 * Special version of the AssertFailed macro to be used within VirtualBoxBase
167 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
168 *
169 * In the debug build, this macro is equivalent to AssertFailed.
170 * In the release build, this macro uses |setError(E_FAIL, ...)| to set the
171 * error info from the asserted expression.
172 *
173 * @see VirtualBoxSupportErrorInfoImpl::setError
174 *
175 */
176#if defined (DEBUG)
177#define ComAssertFailed() AssertFailed()
178#else
179#define ComAssertFailed() \
180 do { \
181 setError(E_FAIL, \
182 "Assertion failed: at '%s' (%d) in %s.\nPlease contact the product vendor!", \
183 __FILE__, __LINE__, __PRETTY_FUNCTION__); \
184 } while (0)
185#endif
186
187/**
188 * Special version of the AssertMsg macro to be used within VirtualBoxBase
189 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
190 *
191 * See ComAssert for more info.
192 *
193 * @param expr Expression which should be true.
194 * @param a printf argument list (in parenthesis).
195 */
196#if defined (DEBUG)
197#define ComAssertMsg(expr, a) AssertMsg(expr, a)
198#else
199#define ComAssertMsg(expr, a) \
200 do { \
201 if (RT_UNLIKELY(!(expr))) \
202 setError(E_FAIL, \
203 "Assertion failed: [%s] at '%s' (%d) in %s.\n%s.\nPlease contact the product vendor!", \
204 #expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
205 } while (0)
206#endif
207
208/**
209 * Special version of the AssertRC macro to be used within VirtualBoxBase
210 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
211 *
212 * See ComAssert for more info.
213 *
214 * @param vrc VBox status code.
215 */
216#if defined (DEBUG)
217#define ComAssertRC(vrc) AssertRC(vrc)
218#else
219#define ComAssertRC(vrc) ComAssertMsgRC(vrc, ("%Rra", vrc))
220#endif
221
222/**
223 * Special version of the AssertMsgRC macro to be used within VirtualBoxBase
224 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
225 *
226 * See ComAssert for more info.
227 *
228 * @param vrc VBox status code.
229 * @param msg printf argument list (in parenthesis).
230 */
231#if defined (DEBUG)
232#define ComAssertMsgRC(vrc, msg) AssertMsgRC(vrc, msg)
233#else
234#define ComAssertMsgRC(vrc, msg) ComAssertMsg(RT_SUCCESS(vrc), msg)
235#endif
236
237/**
238 * Special version of the AssertComRC macro to be used within VirtualBoxBase
239 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
240 *
241 * See ComAssert for more info.
242 *
243 * @param rc COM result code
244 */
245#if defined (DEBUG)
246#define ComAssertComRC(rc) AssertComRC(rc)
247#else
248#define ComAssertComRC(rc) ComAssertMsg(SUCCEEDED(rc), ("COM RC = %Rhrc (0x%08X)", (rc), (rc)))
249#endif
250
251
252/** Special version of ComAssert that returns ret if expr fails */
253#define ComAssertRet(expr, ret) \
254 do { ComAssert(expr); if (!(expr)) return (ret); } while (0)
255/** Special version of ComAssertMsg that returns ret if expr fails */
256#define ComAssertMsgRet(expr, a, ret) \
257 do { ComAssertMsg(expr, a); if (!(expr)) return (ret); } while (0)
258/** Special version of ComAssertRC that returns ret if vrc does not succeed */
259#define ComAssertRCRet(vrc, ret) \
260 do { ComAssertRC(vrc); if (!RT_SUCCESS(vrc)) return (ret); } while (0)
261/** Special version of ComAssertComRC that returns ret if rc does not succeed */
262#define ComAssertComRCRet(rc, ret) \
263 do { ComAssertComRC(rc); if (!SUCCEEDED(rc)) return (ret); } while (0)
264/** Special version of ComAssertComRC that returns rc if rc does not succeed */
265#define ComAssertComRCRetRC(rc) \
266 do { ComAssertComRC(rc); if (!SUCCEEDED(rc)) return (rc); } while (0)
267
268
269/** Special version of ComAssert that evaluates eval and breaks if expr fails */
270#define ComAssertBreak(expr, eval) \
271 if (1) { ComAssert(expr); if (!(expr)) { eval; break; } } else do {} while (0)
272/** Special version of ComAssertMsg that evaluates eval and breaks if expr fails */
273#define ComAssertMsgBreak(expr, a, eval) \
274 if (1) { ComAssertMsg(expr, a); if (!(expr)) { eval; break; } } else do {} while (0)
275/** Special version of ComAssertRC that evaluates eval and breaks if vrc does not succeed */
276#define ComAssertRCBreak(vrc, eval) \
277 if (1) { ComAssertRC(vrc); if (!RT_SUCCESS(vrc)) { eval; break; } } else do {} while (0)
278/** Special version of ComAssertFailed that evaluates eval and breaks */
279#define ComAssertFailedBreak(eval) \
280 if (1) { ComAssertFailed(); { eval; break; } } else do {} while (0)
281/** Special version of ComAssertMsgFailed that evaluates eval and breaks */
282#define ComAssertMsgFailedBreak(msg, eval) \
283 if (1) { ComAssertMsgFailed (msg); { eval; break; } } else do {} while (0)
284/** Special version of ComAssertComRC that evaluates eval and breaks if rc does not succeed */
285#define ComAssertComRCBreak(rc, eval) \
286 if (1) { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { eval; break; } } else do {} while (0)
287/** Special version of ComAssertComRC that just breaks if rc does not succeed */
288#define ComAssertComRCBreakRC(rc) \
289 if (1) { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { break; } } else do {} while (0)
290
291
292/** Special version of ComAssert that evaluates eval and throws it if expr fails */
293#define ComAssertThrow(expr, eval) \
294 if (1) { ComAssert(expr); if (!(expr)) { throw (eval); } } else do {} while (0)
295/** Special version of ComAssertRC that evaluates eval and throws it if vrc does not succeed */
296#define ComAssertRCThrow(vrc, eval) \
297 if (1) { ComAssertRC(vrc); if (!RT_SUCCESS(vrc)) { throw (eval); } } else do {} while (0)
298/** Special version of ComAssertComRC that evaluates eval and throws it if rc does not succeed */
299#define ComAssertComRCThrow(rc, eval) \
300 if (1) { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { throw (eval); } } else do {} while (0)
301/** Special version of ComAssertComRC that just throws rc if rc does not succeed */
302#define ComAssertComRCThrowRC(rc) \
303 if (1) { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { throw rc; } } else do {} while (0)
304/** Special version of ComAssert that throws eval */
305#define ComAssertFailedThrow(eval) \
306 if (1) { ComAssertFailed(); { throw (eval); } } else do {} while (0)
307
308////////////////////////////////////////////////////////////////////////////////
309
310/**
311 * Checks that the pointer argument is not NULL and returns E_INVALIDARG +
312 * extended error info on failure.
313 * @param arg Input pointer-type argument (strings, interface pointers...)
314 */
315#define CheckComArgNotNull(arg) \
316 do { \
317 if (RT_UNLIKELY((arg) == NULL)) \
318 return setError(E_INVALIDARG, tr("Argument %s is NULL"), #arg); \
319 } while (0)
320
321/**
322 * Checks that safe array argument is not NULL and returns E_INVALIDARG +
323 * extended error info on failure.
324 * @param arg Input safe array argument (strings, interface pointers...)
325 */
326#define CheckComArgSafeArrayNotNull(arg) \
327 do { \
328 if (RT_UNLIKELY(ComSafeArrayInIsNull(arg))) \
329 return setError(E_INVALIDARG, tr("Argument %s is NULL"), #arg); \
330 } while (0)
331
332/**
333 * Checks that the string argument is not a NULL or empty string and returns
334 * E_INVALIDARG + extended error info on failure.
335 * @param arg Input string argument (BSTR etc.).
336 */
337#define CheckComArgStrNotEmptyOrNull(arg) \
338 do { \
339 if (RT_UNLIKELY((arg) == NULL || *(arg) == '\0')) \
340 return setError(E_INVALIDARG, \
341 tr("Argument %s is empty or NULL"), #arg); \
342 } while (0)
343
344/**
345 * Checks that the given expression (that must involve the argument) is true and
346 * returns E_INVALIDARG + extended error info on failure.
347 * @param arg Argument.
348 * @param expr Expression to evaluate.
349 */
350#define CheckComArgExpr(arg, expr) \
351 do { \
352 if (RT_UNLIKELY(!(expr))) \
353 return setError(E_INVALIDARG, \
354 tr("Argument %s is invalid (must be %s)"), #arg, #expr); \
355 } while (0)
356
357/**
358 * Checks that the given expression (that must involve the argument) is true and
359 * returns E_INVALIDARG + extended error info on failure. The error message must
360 * be customized.
361 * @param arg Argument.
362 * @param expr Expression to evaluate.
363 * @param msg Parenthesized printf-like expression (must start with a verb,
364 * like "must be one of...", "is not within...").
365 */
366#define CheckComArgExprMsg(arg, expr, msg) \
367 do { \
368 if (RT_UNLIKELY(!(expr))) \
369 return setError(E_INVALIDARG, tr ("Argument %s %s"), \
370 #arg, Utf8StrFmt msg .c_str()); \
371 } while (0)
372
373/**
374 * Checks that the given pointer to an output argument is valid and returns
375 * E_POINTER + extended error info otherwise.
376 * @param arg Pointer argument.
377 */
378#define CheckComArgOutPointerValid(arg) \
379 do { \
380 if (RT_UNLIKELY(!VALID_PTR(arg))) \
381 return setError(E_POINTER, \
382 tr("Output argument %s points to invalid memory location (%p)"), \
383 #arg, (void *) (arg)); \
384 } while (0)
385
386/**
387 * Checks that the given pointer to an output safe array argument is valid and
388 * returns E_POINTER + extended error info otherwise.
389 * @param arg Safe array argument.
390 */
391#define CheckComArgOutSafeArrayPointerValid(arg) \
392 do { \
393 if (RT_UNLIKELY(ComSafeArrayOutIsNull(arg))) \
394 return setError(E_POINTER, \
395 tr("Output argument %s points to invalid memory location (%p)"), \
396 #arg, (void*)(arg)); \
397 } while (0)
398
399/**
400 * Sets the extended error info and returns E_NOTIMPL.
401 */
402#define ReturnComNotImplemented() \
403 do { \
404 return setError(E_NOTIMPL, tr("Method %s is not implemented"), __FUNCTION__); \
405 } while (0)
406
407/**
408 * Declares an empty constructor and destructor for the given class.
409 * This is useful to prevent the compiler from generating the default
410 * ctor and dtor, which in turn allows to use forward class statements
411 * (instead of including their header files) when declaring data members of
412 * non-fundamental types with constructors (which are always called implicitly
413 * by constructors and by the destructor of the class).
414 *
415 * This macro is to be placed within (the public section of) the class
416 * declaration. Its counterpart, DEFINE_EMPTY_CTOR_DTOR, must be placed
417 * somewhere in one of the translation units (usually .cpp source files).
418 *
419 * @param cls class to declare a ctor and dtor for
420 */
421#define DECLARE_EMPTY_CTOR_DTOR(cls) cls(); ~cls();
422
423/**
424 * Defines an empty constructor and destructor for the given class.
425 * See DECLARE_EMPTY_CTOR_DTOR for more info.
426 */
427#define DEFINE_EMPTY_CTOR_DTOR(cls) \
428 cls::cls() { /*empty*/ } \
429 cls::~cls() { /*empty*/ }
430
431/**
432 * A variant of 'throw' that hits a debug breakpoint first to make
433 * finding the actual thrower possible.
434 */
435#ifdef DEBUG
436#define DebugBreakThrow(a) \
437 do { \
438 RTAssertDebugBreak(); \
439 throw (a); \
440} while (0)
441#else
442#define DebugBreakThrow(a) throw (a)
443#endif
444
445/**
446 * Parent class of VirtualBoxBase which enables translation support (which
447 * Main doesn't have yet, but this provides the tr() function which will one
448 * day provide translations).
449 *
450 * This class sits in between Lockable and VirtualBoxBase only for the one
451 * reason that the USBProxyService wants translation support but is not
452 * implemented as a COM object, which VirtualBoxBase implies.
453 */
454class ATL_NO_VTABLE VirtualBoxTranslatable
455 : public Lockable
456{
457public:
458
459 /**
460 * Placeholder method with which translations can one day be implemented
461 * in Main. This gets called by the tr() function.
462 * @param context
463 * @param pcszSourceText
464 * @param comment
465 * @return
466 */
467 static const char *translate(const char *context,
468 const char *pcszSourceText,
469 const char *comment = 0)
470 {
471 NOREF(context);
472 NOREF(comment);
473 return pcszSourceText;
474 }
475
476 /**
477 * Translates the given text string by calling translate() and passing
478 * the name of the C class as the first argument ("context of
479 * translation"). See VirtualBoxBase::translate() for more info.
480 *
481 * @param aSourceText String to translate.
482 * @param aComment Comment to the string to resolve possible
483 * ambiguities (NULL means no comment).
484 *
485 * @return Translated version of the source string in UTF-8 encoding, or
486 * the source string itself if the translation is not found in the
487 * specified context.
488 */
489 inline static const char *tr(const char *pcszSourceText,
490 const char *aComment = NULL)
491 {
492 return VirtualBoxTranslatable::translate(NULL, // getComponentName(), eventually
493 pcszSourceText,
494 aComment);
495 }
496};
497
498////////////////////////////////////////////////////////////////////////////////
499//
500// VirtualBoxBase
501//
502////////////////////////////////////////////////////////////////////////////////
503
504#define VIRTUALBOXBASE_ADD_VIRTUAL_COMPONENT_METHODS(cls, iface) \
505 virtual const IID& getClassIID() const \
506 { \
507 return cls::getStaticClassIID(); \
508 } \
509 static const IID& getStaticClassIID() \
510 { \
511 return COM_IIDOF(iface); \
512 } \
513 virtual const char* getComponentName() const \
514 { \
515 return cls::getStaticComponentName(); \
516 } \
517 static const char* getStaticComponentName() \
518 { \
519 return #cls; \
520 }
521
522/**
523 * VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT:
524 * This macro must be used once in the declaration of any class derived
525 * from VirtualBoxBase. It implements the pure virtual getClassIID() and
526 * getComponentName() methods. If this macro is not present, instances
527 * of a class derived from VirtualBoxBase cannot be instantiated.
528 *
529 * @param X The class name, e.g. "Class".
530 * @param IX The interface name which this class implements, e.g. "IClass".
531 */
532#ifdef VBOX_WITH_XPCOM
533 #define VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(cls, iface) \
534 VIRTUALBOXBASE_ADD_VIRTUAL_COMPONENT_METHODS(cls, iface)
535#else // #ifdef VBOX_WITH_XPCOM
536 #define VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(cls, iface) \
537 VIRTUALBOXBASE_ADD_VIRTUAL_COMPONENT_METHODS(cls, iface) \
538 STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid) \
539 { \
540 const _ATL_INTMAP_ENTRY* pEntries = cls::_GetEntries(); \
541 Assert(pEntries); \
542 if (!pEntries) \
543 return S_FALSE; \
544 BOOL bSupports = FALSE; \
545 BOOL bISupportErrorInfoFound = FALSE; \
546 while (pEntries->pFunc != NULL && !bSupports) \
547 { \
548 if (!bISupportErrorInfoFound) \
549 bISupportErrorInfoFound = InlineIsEqualGUID(*(pEntries->piid), IID_ISupportErrorInfo); \
550 else \
551 bSupports = InlineIsEqualGUID(*(pEntries->piid), riid); \
552 pEntries++; \
553 } \
554 Assert(bISupportErrorInfoFound); \
555 return bSupports ? S_OK : S_FALSE; \
556 }
557#endif // #ifdef VBOX_WITH_XPCOM
558
559/**
560 * Abstract base class for all component classes implementing COM
561 * interfaces of the VirtualBox COM library.
562 *
563 * Declares functionality that should be available in all components.
564 *
565 * Among the basic functionality implemented by this class is the primary object
566 * state that indicates if the object is ready to serve the calls, and if not,
567 * what stage it is currently at. Here is the primary state diagram:
568 *
569 * +-------------------------------------------------------+
570 * | |
571 * | (InitFailed) -----------------------+ |
572 * | ^ | |
573 * v | v |
574 * [*] ---> NotReady ----> (InInit) -----> Ready -----> (InUninit) ----+
575 * ^ |
576 * | v
577 * | Limited
578 * | |
579 * +-------+
580 *
581 * The object is fully operational only when its state is Ready. The Limited
582 * state means that only some vital part of the object is operational, and it
583 * requires some sort of reinitialization to become fully operational. The
584 * NotReady state means the object is basically dead: it either was not yet
585 * initialized after creation at all, or was uninitialized and is waiting to be
586 * destroyed when the last reference to it is released. All other states are
587 * transitional.
588 *
589 * The NotReady->InInit->Ready, NotReady->InInit->Limited and
590 * NotReady->InInit->InitFailed transition is done by the AutoInitSpan smart
591 * class.
592 *
593 * The Limited->InInit->Ready, Limited->InInit->Limited and
594 * Limited->InInit->InitFailed transition is done by the AutoReinitSpan smart
595 * class.
596 *
597 * The Ready->InUninit->NotReady and InitFailed->InUninit->NotReady
598 * transitions are done by the AutoUninitSpan smart class.
599 *
600 * In order to maintain the primary state integrity and declared functionality
601 * all subclasses must:
602 *
603 * 1) Use the above Auto*Span classes to perform state transitions. See the
604 * individual class descriptions for details.
605 *
606 * 2) All public methods of subclasses (i.e. all methods that can be called
607 * directly, not only from within other methods of the subclass) must have a
608 * standard prolog as described in the AutoCaller and AutoLimitedCaller
609 * documentation. Alternatively, they must use addCaller()/releaseCaller()
610 * directly (and therefore have both the prolog and the epilog), but this is
611 * not recommended.
612 */
613class ATL_NO_VTABLE VirtualBoxBase
614 : public VirtualBoxTranslatable,
615 public CComObjectRootEx<CComMultiThreadModel>
616#if !defined (VBOX_WITH_XPCOM)
617 , public ISupportErrorInfo
618#endif
619{
620public:
621 enum State { NotReady, Ready, InInit, InUninit, InitFailed, Limited };
622
623 VirtualBoxBase();
624 virtual ~VirtualBoxBase();
625
626 /**
627 * Uninitialization method.
628 *
629 * Must be called by all final implementations (component classes) when the
630 * last reference to the object is released, before calling the destructor.
631 *
632 * This method is also automatically called by the uninit() method of this
633 * object's parent if this object is a dependent child of a class derived
634 * from VirtualBoxBaseWithChildren (see
635 * VirtualBoxBaseWithChildren::addDependentChild).
636 *
637 * @note Never call this method the AutoCaller scope or after the
638 * #addCaller() call not paired by #releaseCaller() because it is a
639 * guaranteed deadlock. See AutoUninitSpan for details.
640 */
641 virtual void uninit()
642 { }
643
644 virtual HRESULT addCaller(State *aState = NULL,
645 bool aLimited = false);
646 virtual void releaseCaller();
647
648 /**
649 * Adds a limited caller. This method is equivalent to doing
650 * <tt>addCaller (aState, true)</tt>, but it is preferred because provides
651 * better self-descriptiveness. See #addCaller() for more info.
652 */
653 HRESULT addLimitedCaller(State *aState = NULL)
654 {
655 return addCaller(aState, true /* aLimited */);
656 }
657
658 /**
659 * Pure virtual method for simple run-time type identification without
660 * having to enable C++ RTTI.
661 *
662 * This *must* be implemented by every subclass deriving from VirtualBoxBase;
663 * use the VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT macro to do that most easily.
664 */
665 virtual const IID& getClassIID() const = 0;
666
667 /**
668 * Pure virtual method for simple run-time type identification without
669 * having to enable C++ RTTI.
670 *
671 * This *must* be implemented by every subclass deriving from VirtualBoxBase;
672 * use the VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT macro to do that most easily.
673 */
674 virtual const char* getComponentName() const = 0;
675
676 /**
677 * Virtual method which determines the locking class to be used for validating
678 * lock order with the standard member lock handle. This method is overridden
679 * in a number of subclasses.
680 */
681 virtual VBoxLockingClass getLockingClass() const
682 {
683 return LOCKCLASS_OTHEROBJECT;
684 }
685
686 virtual RWLockHandle *lockHandle() const;
687
688 /**
689 * Returns a lock handle used to protect the primary state fields (used by
690 * #addCaller(), AutoInitSpan, AutoUninitSpan, etc.). Only intended to be
691 * used for similar purposes in subclasses. WARNING: NO any other locks may
692 * be requested while holding this lock!
693 */
694 WriteLockHandle *stateLockHandle() { return &mStateLock; }
695
696 static HRESULT setErrorInternal(HRESULT aResultCode,
697 const GUID &aIID,
698 const char *aComponent,
699 const Utf8Str &aText,
700 bool aWarning,
701 bool aLogIt);
702
703 HRESULT setError(HRESULT aResultCode, const char *pcsz, ...);
704 HRESULT setWarning(HRESULT aResultCode, const char *pcsz, ...);
705 HRESULT setErrorNoLog(HRESULT aResultCode, const char *pcsz, ...);
706
707private:
708
709 void setState(State aState)
710 {
711 Assert(mState != aState);
712 mState = aState;
713 mStateChangeThread = RTThreadSelf();
714 }
715
716 /** Primary state of this object */
717 State mState;
718 /** Thread that caused the last state change */
719 RTTHREAD mStateChangeThread;
720 /** Total number of active calls to this object */
721 unsigned mCallers;
722 /** Posted when the number of callers drops to zero */
723 RTSEMEVENT mZeroCallersSem;
724 /** Posted when the object goes from InInit/InUninit to some other state */
725 RTSEMEVENTMULTI mInitUninitSem;
726 /** Number of threads waiting for mInitUninitDoneSem */
727 unsigned mInitUninitWaiters;
728
729 /** Protects access to state related data members */
730 WriteLockHandle mStateLock;
731
732 /** User-level object lock for subclasses */
733 mutable RWLockHandle *mObjectLock;
734
735 friend class AutoInitSpan;
736 friend class AutoReinitSpan;
737 friend class AutoUninitSpan;
738};
739
740/**
741 * Dummy macro that is used to shut down Qt's lupdate tool warnings in some
742 * situations. This macro needs to be present inside (better at the very
743 * beginning) of the declaration of the class that inherits from
744 * VirtualBoxSupportTranslation template, to make lupdate happy.
745 */
746#define Q_OBJECT
747
748////////////////////////////////////////////////////////////////////////////////
749
750/**
751 * Base class to track VirtualBoxBaseNEXT chlidren of the component.
752 *
753 * This class is a preferable VirtualBoxBase replacement for components that
754 * operate with collections of child components. It gives two useful
755 * possibilities:
756 *
757 * <ol><li>
758 * Given an IUnknown instance, it's possible to quickly determine
759 * whether this instance represents a child object that belongs to the
760 * given component, and if so, get a valid VirtualBoxBase pointer to the
761 * child object. The returned pointer can be then safely casted to the
762 * actual class of the child object (to get access to its "internal"
763 * non-interface methods) provided that no other child components implement
764 * the same original COM interface IUnknown is queried from.
765 * </li><li>
766 * When the parent object uninitializes itself, it can easily uninitialize
767 * all its VirtualBoxBase derived children (using their
768 * VirtualBoxBase::uninit() implementations). This is done simply by
769 * calling the #uninitDependentChildren() method.
770 * </li></ol>
771 *
772 * In order to let the above work, the following must be done:
773 * <ol><li>
774 * When a child object is initialized, it calls #addDependentChild() of
775 * its parent to register itself within the list of dependent children.
776 * </li><li>
777 * When the child object it is uninitialized, it calls
778 * #removeDependentChild() to unregister itself.
779 * </li></ol>
780 *
781 * Note that if the parent object does not call #uninitDependentChildren() when
782 * it gets uninitialized, it must call uninit() methods of individual children
783 * manually to disconnect them; a failure to do so will cause crashes in these
784 * methods when children get destroyed. The same applies to children not calling
785 * #removeDependentChild() when getting destroyed.
786 *
787 * Note that children added by #addDependentChild() are <b>weakly</b> referenced
788 * (i.e. AddRef() is not called), so when a child object is deleted externally
789 * (because it's reference count goes to zero), it will automatically remove
790 * itself from the map of dependent children provided that it follows the rules
791 * described here.
792 *
793 * Access to the child list is serialized using the #childrenLock() lock handle
794 * (which defaults to the general object lock handle (see
795 * VirtualBoxBase::lockHandle()). This lock is used by all add/remove methods of
796 * this class so be aware of the need to preserve the {parent, child} lock order
797 * when calling these methods.
798 *
799 * Read individual method descriptions to get further information.
800 *
801 * @todo This is a VirtualBoxBaseWithChildren equivalent that uses the
802 * VirtualBoxBaseNEXT implementation. Will completely supersede
803 * VirtualBoxBaseWithChildren after the old VirtualBoxBase implementation
804 * has gone.
805 */
806class VirtualBoxBaseWithChildrenNEXT : public VirtualBoxBase
807{
808public:
809
810 VirtualBoxBaseWithChildrenNEXT()
811 {}
812
813 virtual ~VirtualBoxBaseWithChildrenNEXT()
814 {}
815
816 /**
817 * Lock handle to use when adding/removing child objects from the list of
818 * children. It is guaranteed that no any other lock is requested in methods
819 * of this class while holding this lock.
820 *
821 * @warning By default, this simply returns the general object's lock handle
822 * (see VirtualBoxBase::lockHandle()) which is sufficient for most
823 * cases.
824 */
825 virtual RWLockHandle *childrenLock() { return lockHandle(); }
826
827 /**
828 * Adds the given child to the list of dependent children.
829 *
830 * Usually gets called from the child's init() method.
831 *
832 * @note @a aChild (unless it is in InInit state) must be protected by
833 * VirtualBoxBase::AutoCaller to make sure it is not uninitialized on
834 * another thread during this method's call.
835 *
836 * @note When #childrenLock() is not overloaded (returns the general object
837 * lock) and this method is called from under the child's read or
838 * write lock, make sure the {parent, child} locking order is
839 * preserved by locking the callee (this object) for writing before
840 * the child's lock.
841 *
842 * @param aChild Child object to add (must inherit VirtualBoxBase AND
843 * implement some interface).
844 *
845 * @note Locks #childrenLock() for writing.
846 */
847 template<class C>
848 void addDependentChild(C *aChild)
849 {
850 AssertReturnVoid(aChild != NULL);
851 doAddDependentChild(ComPtr<IUnknown>(aChild), aChild);
852 }
853
854 /**
855 * Equivalent to template <class C> void addDependentChild (C *aChild)
856 * but takes a ComObjPtr<C> argument.
857 */
858 template<class C>
859 void addDependentChild(const ComObjPtr<C> &aChild)
860 {
861 AssertReturnVoid(!aChild.isNull());
862 doAddDependentChild(ComPtr<IUnknown>(static_cast<C *>(aChild)), aChild);
863 }
864
865 /**
866 * Removes the given child from the list of dependent children.
867 *
868 * Usually gets called from the child's uninit() method.
869 *
870 * Keep in mind that the called (parent) object may be no longer available
871 * (i.e. may be deleted deleted) after this method returns, so you must not
872 * call any other parent's methods after that!
873 *
874 * @note Locks #childrenLock() for writing.
875 *
876 * @note @a aChild (unless it is in InUninit state) must be protected by
877 * VirtualBoxBase::AutoCaller to make sure it is not uninitialized on
878 * another thread during this method's call.
879 *
880 * @note When #childrenLock() is not overloaded (returns the general object
881 * lock) and this method is called from under the child's read or
882 * write lock, make sure the {parent, child} locking order is
883 * preserved by locking the callee (this object) for writing before
884 * the child's lock. This is irrelevant when the method is called from
885 * under this object's VirtualBoxBaseProto::AutoUninitSpan (i.e. in
886 * InUninit state) since in this case no locking is done.
887 *
888 * @param aChild Child object to remove.
889 *
890 * @note Locks #childrenLock() for writing.
891 */
892 template<class C>
893 void removeDependentChild(C *aChild)
894 {
895 AssertReturnVoid(aChild != NULL);
896 doRemoveDependentChild(ComPtr<IUnknown>(aChild));
897 }
898
899 /**
900 * Equivalent to template <class C> void removeDependentChild (C *aChild)
901 * but takes a ComObjPtr<C> argument.
902 */
903 template<class C>
904 void removeDependentChild(const ComObjPtr<C> &aChild)
905 {
906 AssertReturnVoid(!aChild.isNull());
907 doRemoveDependentChild(ComPtr<IUnknown>(static_cast<C *>(aChild)));
908 }
909
910protected:
911
912 void uninitDependentChildren();
913
914 VirtualBoxBase *getDependentChild(const ComPtr<IUnknown> &aUnk);
915
916private:
917 void doAddDependentChild(IUnknown *aUnk, VirtualBoxBase *aChild);
918 void doRemoveDependentChild(IUnknown *aUnk);
919
920 typedef std::map<IUnknown*, VirtualBoxBase*> DependentChildren;
921 DependentChildren mDependentChildren;
922};
923
924////////////////////////////////////////////////////////////////////////////////
925
926////////////////////////////////////////////////////////////////////////////////
927
928
929/**
930 * Simple template that manages data structure allocation/deallocation
931 * and supports data pointer sharing (the instance that shares the pointer is
932 * not responsible for memory deallocation as opposed to the instance that
933 * owns it).
934 */
935template <class D>
936class Shareable
937{
938public:
939
940 Shareable() : mData (NULL), mIsShared(FALSE) {}
941 ~Shareable() { free(); }
942
943 void allocate() { attach(new D); }
944
945 virtual void free() {
946 if (mData) {
947 if (!mIsShared)
948 delete mData;
949 mData = NULL;
950 mIsShared = false;
951 }
952 }
953
954 void attach(D *d) {
955 AssertMsg(d, ("new data must not be NULL"));
956 if (d && mData != d) {
957 if (mData && !mIsShared)
958 delete mData;
959 mData = d;
960 mIsShared = false;
961 }
962 }
963
964 void attach(Shareable &d) {
965 AssertMsg(
966 d.mData == mData || !d.mIsShared,
967 ("new data must not be shared")
968 );
969 if (this != &d && !d.mIsShared) {
970 attach(d.mData);
971 d.mIsShared = true;
972 }
973 }
974
975 void share(D *d) {
976 AssertMsg(d, ("new data must not be NULL"));
977 if (mData != d) {
978 if (mData && !mIsShared)
979 delete mData;
980 mData = d;
981 mIsShared = true;
982 }
983 }
984
985 void share(const Shareable &d) { share(d.mData); }
986
987 void attachCopy(const D *d) {
988 AssertMsg(d, ("data to copy must not be NULL"));
989 if (d)
990 attach(new D(*d));
991 }
992
993 void attachCopy(const Shareable &d) {
994 attachCopy(d.mData);
995 }
996
997 virtual D *detach() {
998 D *d = mData;
999 mData = NULL;
1000 mIsShared = false;
1001 return d;
1002 }
1003
1004 D *data() const {
1005 return mData;
1006 }
1007
1008 D *operator->() const {
1009 AssertMsg(mData, ("data must not be NULL"));
1010 return mData;
1011 }
1012
1013 bool isNull() const { return mData == NULL; }
1014 bool operator!() const { return isNull(); }
1015
1016 bool isShared() const { return mIsShared; }
1017
1018protected:
1019
1020 D *mData;
1021 bool mIsShared;
1022};
1023
1024/// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
1025/**
1026 * Simple template that enhances Shareable<> and supports data
1027 * backup/rollback/commit (using the copy constructor of the managed data
1028 * structure).
1029 */
1030template<class D>
1031class Backupable : public Shareable<D>
1032{
1033public:
1034
1035 Backupable() : Shareable<D> (), mBackupData(NULL) {}
1036
1037 void free()
1038 {
1039 AssertMsg(this->mData || !mBackupData, ("backup must be NULL if data is NULL"));
1040 rollback();
1041 Shareable<D>::free();
1042 }
1043
1044 D *detach()
1045 {
1046 AssertMsg(this->mData || !mBackupData, ("backup must be NULL if data is NULL"));
1047 rollback();
1048 return Shareable<D>::detach();
1049 }
1050
1051 void share(const Backupable &d)
1052 {
1053 AssertMsg(!d.isBackedUp(), ("data to share must not be backed up"));
1054 if (!d.isBackedUp())
1055 Shareable<D>::share(d.mData);
1056 }
1057
1058 /**
1059 * Stores the current data pointer in the backup area, allocates new data
1060 * using the copy constructor on current data and makes new data active.
1061 */
1062 void backup()
1063 {
1064 AssertMsg(this->mData, ("data must not be NULL"));
1065 if (this->mData && !mBackupData)
1066 {
1067 D *pNewData = new D(*this->mData);
1068 mBackupData = this->mData;
1069 this->mData = pNewData;
1070 }
1071 }
1072
1073 /**
1074 * Deletes new data created by #backup() and restores previous data pointer
1075 * stored in the backup area, making it active again.
1076 */
1077 void rollback()
1078 {
1079 if (this->mData && mBackupData)
1080 {
1081 delete this->mData;
1082 this->mData = mBackupData;
1083 mBackupData = NULL;
1084 }
1085 }
1086
1087 /**
1088 * Commits current changes by deleting backed up data and clearing up the
1089 * backup area. The new data pointer created by #backup() remains active
1090 * and becomes the only managed pointer.
1091 *
1092 * This method is much faster than #commitCopy() (just a single pointer
1093 * assignment operation), but makes the previous data pointer invalid
1094 * (because it is freed). For this reason, this method must not be
1095 * used if it's possible that data managed by this instance is shared with
1096 * some other Shareable instance. See #commitCopy().
1097 */
1098 void commit()
1099 {
1100 if (this->mData && mBackupData)
1101 {
1102 if (!this->mIsShared)
1103 delete mBackupData;
1104 mBackupData = NULL;
1105 this->mIsShared = false;
1106 }
1107 }
1108
1109 /**
1110 * Commits current changes by assigning new data to the previous data
1111 * pointer stored in the backup area using the assignment operator.
1112 * New data is deleted, the backup area is cleared and the previous data
1113 * pointer becomes active and the only managed pointer.
1114 *
1115 * This method is slower than #commit(), but it keeps the previous data
1116 * pointer valid (i.e. new data is copied to the same memory location).
1117 * For that reason it's safe to use this method on instances that share
1118 * managed data with other Shareable instances.
1119 */
1120 void commitCopy()
1121 {
1122 if (this->mData && mBackupData)
1123 {
1124 *mBackupData = *(this->mData);
1125 delete this->mData;
1126 this->mData = mBackupData;
1127 mBackupData = NULL;
1128 }
1129 }
1130
1131 void assignCopy(const D *pData)
1132 {
1133 AssertMsg(this->mData, ("data must not be NULL"));
1134 AssertMsg(pData, ("data to copy must not be NULL"));
1135 if (this->mData && pData)
1136 {
1137 if (!mBackupData)
1138 {
1139 D *pNewData = new D(*pData);
1140 mBackupData = this->mData;
1141 this->mData = pNewData;
1142 }
1143 else
1144 *this->mData = *pData;
1145 }
1146 }
1147
1148 void assignCopy(const Backupable &d)
1149 {
1150 assignCopy(d.mData);
1151 }
1152
1153 bool isBackedUp() const
1154 {
1155 return mBackupData != NULL;
1156 }
1157
1158 D *backedUpData() const
1159 {
1160 return mBackupData;
1161 }
1162
1163protected:
1164
1165 D *mBackupData;
1166};
1167
1168#endif // !____H_VIRTUALBOXBASEIMPL
1169
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