VirtualBox

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

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

Main: back out r42503

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 104.5 KB
Line 
1/** @file
2 *
3 * VirtualBox COM base classes definition
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * 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 "VBox/com/string.h"
26#include "VBox/com/Guid.h"
27#include "VBox/com/ptr.h"
28#include "VBox/com/ErrorInfo.h"
29
30#include "VBox/com/VirtualBox.h"
31
32#include <VBox/settings.h>
33
34#include "AutoLock.h"
35
36using namespace com;
37using namespace util;
38
39#include <iprt/cdefs.h>
40#include <iprt/critsect.h>
41#include <iprt/thread.h>
42
43#include <list>
44#include <map>
45
46#if !defined (VBOX_WITH_XPCOM)
47
48#include <atlcom.h>
49
50/* use a special version of the singleton class factory,
51 * see KB811591 in msdn for more info. */
52
53#undef DECLARE_CLASSFACTORY_SINGLETON
54#define DECLARE_CLASSFACTORY_SINGLETON(obj) DECLARE_CLASSFACTORY_EX(CMyComClassFactorySingleton<obj>)
55
56template <class T>
57class CMyComClassFactorySingleton : public CComClassFactory
58{
59public:
60 CMyComClassFactorySingleton() : m_hrCreate(S_OK){}
61 virtual ~CMyComClassFactorySingleton(){}
62 // IClassFactory
63 STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj)
64 {
65 HRESULT hRes = E_POINTER;
66 if (ppvObj != NULL)
67 {
68 *ppvObj = NULL;
69 // Aggregation is not supported in singleton objects.
70 ATLASSERT(pUnkOuter == NULL);
71 if (pUnkOuter != NULL)
72 hRes = CLASS_E_NOAGGREGATION;
73 else
74 {
75 if (m_hrCreate == S_OK && m_spObj == NULL)
76 {
77 Lock();
78 __try
79 {
80 // Fix: The following If statement was moved inside the __try statement.
81 // Did another thread arrive here first?
82 if (m_hrCreate == S_OK && m_spObj == NULL)
83 {
84 // lock the module to indicate activity
85 // (necessary for the monitor shutdown thread to correctly
86 // terminate the module in case when CreateInstance() fails)
87 _pAtlModule->Lock();
88 CComObjectCached<T> *p;
89 m_hrCreate = CComObjectCached<T>::CreateInstance(&p);
90 if (SUCCEEDED(m_hrCreate))
91 {
92 m_hrCreate = p->QueryInterface(IID_IUnknown, (void**)&m_spObj);
93 if (FAILED(m_hrCreate))
94 {
95 delete p;
96 }
97 }
98 _pAtlModule->Unlock();
99 }
100 }
101 __finally
102 {
103 Unlock();
104 }
105 }
106 if (m_hrCreate == S_OK)
107 {
108 hRes = m_spObj->QueryInterface(riid, ppvObj);
109 }
110 else
111 {
112 hRes = m_hrCreate;
113 }
114 }
115 }
116 return hRes;
117 }
118 HRESULT m_hrCreate;
119 CComPtr<IUnknown> m_spObj;
120};
121
122#endif /* !defined (VBOX_WITH_XPCOM) */
123
124// macros
125////////////////////////////////////////////////////////////////////////////////
126
127/**
128 * Special version of the Assert macro to be used within VirtualBoxBase
129 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
130 *
131 * In the debug build, this macro is equivalent to Assert.
132 * In the release build, this macro uses |setError (E_FAIL, ...)| to set the
133 * error info from the asserted expression.
134 *
135 * @see VirtualBoxSupportErrorInfoImpl::setError
136 *
137 * @param expr Expression which should be true.
138 */
139#if defined (DEBUG)
140#define ComAssert(expr) Assert (expr)
141#else
142#define ComAssert(expr) \
143 do { \
144 if (!(expr)) \
145 setError (E_FAIL, "Assertion failed: [%s] at '%s' (%d) in %s.\n" \
146 "Please contact the product vendor!", \
147 #expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
148 } while (0)
149#endif
150
151/**
152 * Special version of the AssertMsg macro to be used within VirtualBoxBase
153 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
154 *
155 * See ComAssert for more info.
156 *
157 * @param expr Expression which should be true.
158 * @param a printf argument list (in parenthesis).
159 */
160#if defined (DEBUG)
161#define ComAssertMsg(expr, a) AssertMsg (expr, a)
162#else
163#define ComAssertMsg(expr, a) \
164 do { \
165 if (!(expr)) \
166 setError (E_FAIL, "Assertion failed: [%s] at '%s' (%d) in %s.\n" \
167 "%s.\n" \
168 "Please contact the product vendor!", \
169 #expr, __FILE__, __LINE__, __PRETTY_FUNCTION__, Utf8StrFmt a .raw()); \
170 } while (0)
171#endif
172
173/**
174 * Special version of the AssertRC macro to be used within VirtualBoxBase
175 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
176 *
177 * See ComAssert for more info.
178 *
179 * @param vrc VBox status code.
180 */
181#if defined (DEBUG)
182#define ComAssertRC(vrc) AssertRC (vrc)
183#else
184#define ComAssertRC(vrc) ComAssertMsgRC (vrc, ("%Rra", vrc))
185#endif
186
187/**
188 * Special version of the AssertMsgRC macro to be used within VirtualBoxBase
189 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
190 *
191 * See ComAssert for more info.
192 *
193 * @param vrc VBox status code.
194 * @param msg printf argument list (in parenthesis).
195 */
196#if defined (DEBUG)
197#define ComAssertMsgRC(vrc, msg) AssertMsgRC (vrc, msg)
198#else
199#define ComAssertMsgRC(vrc, msg) ComAssertMsg (RT_SUCCESS (vrc), msg)
200#endif
201
202
203/**
204 * Special version of the AssertFailed macro to be used within VirtualBoxBase
205 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
206 *
207 * See ComAssert for more info.
208 */
209#if defined (DEBUG)
210#define ComAssertFailed() AssertFailed()
211#else
212#define ComAssertFailed() \
213 do { \
214 setError (E_FAIL, "Assertion failed at '%s' (%d) in %s.\n" \
215 "Please contact the product vendor!", \
216 __FILE__, __LINE__, __PRETTY_FUNCTION__); \
217 } while (0)
218#endif
219
220/**
221 * Special version of the AssertMsgFailed macro to be used within VirtualBoxBase
222 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
223 *
224 * See ComAssert for more info.
225 *
226 * @param a printf argument list (in parenthesis).
227 */
228#if defined (DEBUG)
229#define ComAssertMsgFailed(a) AssertMsgFailed(a)
230#else
231#define ComAssertMsgFailed(a) \
232 do { \
233 setError (E_FAIL, "Assertion failed at '%s' (%d) in %s.\n" \
234 "%s.\n" \
235 "Please contact the product vendor!", \
236 __FILE__, __LINE__, __PRETTY_FUNCTION__, Utf8StrFmt a .raw()); \
237 } while (0)
238#endif
239
240/**
241 * Special version of the ComAssertMsgFailed macro that additionally takes
242 * line number, file and function arguments to inject an assertion position
243 * that differs from the position where this macro is instantiated.
244 *
245 * @param a printf argument list (in parenthesis).
246 * @param file, line, func Line number (int), file and function (const char *).
247 */
248#if defined (DEBUG)
249#define ComAssertMsgFailedPos(a, file, line, func) \
250 do { \
251 AssertMsg1 ((const char *) 0, line, file, func); \
252 AssertMsg2 a; \
253 AssertBreakpoint(); \
254 } while (0)
255#else
256#define ComAssertMsgFailedPos(a, file, line, func) \
257 do { \
258 setError (E_FAIL, \
259 "Assertion failed at '%s' (%d) in %s.\n" \
260 "%s.\n" \
261 "Please contact the product vendor!", \
262 file, line, func, Utf8StrFmt a .raw()); \
263 } while (0)
264#endif
265
266/**
267 * Special version of the AssertComRC macro to be used within VirtualBoxBase
268 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
269 *
270 * See ComAssert for more info.
271 *
272 * @param rc COM result code
273 */
274#if defined (DEBUG)
275#define ComAssertComRC(rc) AssertComRC (rc)
276#else
277#define ComAssertComRC(rc) ComAssertMsg (SUCCEEDED (rc), ("COM RC = %Rhrc (0x%08X)", (rc), (rc)))
278#endif
279
280
281/** Special version of ComAssert that returns ret if expr fails */
282#define ComAssertRet(expr, ret) \
283 do { ComAssert (expr); if (!(expr)) return (ret); } while (0)
284/** Special version of ComAssertMsg that returns ret if expr fails */
285#define ComAssertMsgRet(expr, a, ret) \
286 do { ComAssertMsg (expr, a); if (!(expr)) return (ret); } while (0)
287/** Special version of ComAssertRC that returns ret if vrc does not succeed */
288#define ComAssertRCRet(vrc, ret) \
289 do { ComAssertRC (vrc); if (!RT_SUCCESS (vrc)) return (ret); } while (0)
290/** Special version of ComAssertMsgRC that returns ret if vrc does not succeed */
291#define ComAssertMsgRCRet(vrc, msg, ret) \
292 do { ComAssertMsgRC (vrc, msg); if (!RT_SUCCESS (vrc)) return (ret); } while (0)
293/** Special version of ComAssertFailed that returns ret */
294#define ComAssertFailedRet(ret) \
295 do { ComAssertFailed(); return (ret); } while (0)
296/** Special version of ComAssertMsgFailed that returns ret */
297#define ComAssertMsgFailedRet(msg, ret) \
298 do { ComAssertMsgFailed (msg); return (ret); } while (0)
299/** Special version of ComAssertComRC that returns ret if rc does not succeed */
300#define ComAssertComRCRet(rc, ret) \
301 do { ComAssertComRC (rc); if (!SUCCEEDED (rc)) return (ret); } while (0)
302/** Special version of ComAssertComRC that returns rc if rc does not succeed */
303#define ComAssertComRCRetRC(rc) \
304 do { ComAssertComRC (rc); if (!SUCCEEDED (rc)) return (rc); } while (0)
305
306
307/** Special version of ComAssert that evaluates eval and breaks if expr fails */
308#define ComAssertBreak(expr, eval) \
309 if (1) { ComAssert (expr); if (!(expr)) { eval; break; } } else do {} while (0)
310/** Special version of ComAssertMsg that evaluates eval and breaks if expr fails */
311#define ComAssertMsgBreak(expr, a, eval) \
312 if (1) { ComAssertMsg (expr, a); if (!(expr)) { eval; break; } } else do {} while (0)
313/** Special version of ComAssertRC that evaluates eval and breaks if vrc does not succeed */
314#define ComAssertRCBreak(vrc, eval) \
315 if (1) { ComAssertRC (vrc); if (!RT_SUCCESS (vrc)) { eval; break; } } else do {} while (0)
316/** Special version of ComAssertMsgRC that evaluates eval and breaks if vrc does not succeed */
317#define ComAssertMsgRCBreak(vrc, msg, eval) \
318 if (1) { ComAssertMsgRC (vrc, msg); if (!RT_SUCCESS (vrc)) { eval; break; } } else do {} while (0)
319/** Special version of ComAssertFailed that evaluates eval and breaks */
320#define ComAssertFailedBreak(eval) \
321 if (1) { ComAssertFailed(); { eval; break; } } else do {} while (0)
322/** Special version of ComAssertMsgFailed that evaluates eval and breaks */
323#define ComAssertMsgFailedBreak(msg, eval) \
324 if (1) { ComAssertMsgFailed (msg); { eval; break; } } else do {} while (0)
325/** Special version of ComAssertComRC that evaluates eval and breaks if rc does not succeed */
326#define ComAssertComRCBreak(rc, eval) \
327 if (1) { ComAssertComRC (rc); if (!SUCCEEDED (rc)) { eval; break; } } else do {} while (0)
328/** Special version of ComAssertComRC that just breaks if rc does not succeed */
329#define ComAssertComRCBreakRC(rc) \
330 if (1) { ComAssertComRC (rc); if (!SUCCEEDED (rc)) { break; } } else do {} while (0)
331
332
333/** Special version of ComAssert that evaluates eval and throws it if expr fails */
334#define ComAssertThrow(expr, eval) \
335 if (1) { ComAssert (expr); if (!(expr)) { throw (eval); } } else do {} while (0)
336/** Special version of ComAssertMsg that evaluates eval and throws it if expr fails */
337#define ComAssertMsgThrow(expr, a, eval) \
338 if (1) { ComAssertMsg (expr, a); if (!(expr)) { throw (eval); } } else do {} while (0)
339/** Special version of ComAssertRC that evaluates eval and throws it if vrc does not succeed */
340#define ComAssertRCThrow(vrc, eval) \
341 if (1) { ComAssertRC (vrc); if (!RT_SUCCESS (vrc)) { throw (eval); } } else do {} while (0)
342/** Special version of ComAssertMsgRC that evaluates eval and throws it if vrc does not succeed */
343#define ComAssertMsgRCThrow(vrc, msg, eval) \
344 if (1) { ComAssertMsgRC (vrc, msg); if (!RT_SUCCESS (vrc)) { throw (eval); } } else do {} while (0)
345/** Special version of ComAssertFailed that evaluates eval and throws it */
346#define ComAssertFailedThrow(eval) \
347 if (1) { ComAssertFailed(); { throw (eval); } } else do {} while (0)
348/** Special version of ComAssertMsgFailed that evaluates eval and throws it */
349#define ComAssertMsgFailedThrow(msg, eval) \
350 if (1) { ComAssertMsgFailed (msg); { throw (eval); } } else do {} while (0)
351/** Special version of ComAssertComRC that evaluates eval and throws it if rc does not succeed */
352#define ComAssertComRCThrow(rc, eval) \
353 if (1) { ComAssertComRC (rc); if (!SUCCEEDED (rc)) { throw (eval); } } else do {} while (0)
354/** Special version of ComAssertComRC that just throws rc if rc does not succeed */
355#define ComAssertComRCThrowRC(rc) \
356 if (1) { ComAssertComRC (rc); if (!SUCCEEDED (rc)) { throw rc; } } else do {} while (0)
357
358////////////////////////////////////////////////////////////////////////////////
359
360/**
361 * Checks that the pointer argument is not NULL and returns E_INVALIDARG +
362 * extended error info on failure.
363 * @param arg Input pointer-type argument (strings, interface pointers...)
364 */
365#define CheckComArgNotNull(arg) \
366 do { \
367 if ((arg) == NULL) \
368 return setError (E_INVALIDARG, tr ("Argument %s is NULL"), #arg); \
369 } while (0)
370
371/**
372 * Checks that safe array argument is not NULL and returns E_INVALIDARG +
373 * extended error info on failure.
374 * @param arg Input safe array argument (strings, interface pointers...)
375 */
376#define CheckComArgSafeArrayNotNull(arg) \
377 do { \
378 if (ComSafeArrayInIsNull (arg)) \
379 return setError (E_INVALIDARG, tr ("Argument %s is NULL"), #arg); \
380 } while (0)
381
382/**
383 * Checks that the string argument is not a NULL or empty string and returns
384 * E_INVALIDARG + extended error info on failure.
385 * @param arg Input string argument (BSTR etc.).
386 */
387#define CheckComArgStrNotEmptyOrNull(arg) \
388 do { \
389 if ((arg) == NULL || *(arg) == '\0') \
390 return setError (E_INVALIDARG, \
391 tr ("Argument %s is emtpy or NULL"), #arg); \
392 } while (0)
393
394/**
395 * Checks that the given expression (that must involve the argument) is true and
396 * returns E_INVALIDARG + extended error info on failure.
397 * @param arg Argument.
398 * @param expr Expression to evaluate.
399 */
400#define CheckComArgExpr(arg, expr) \
401 do { \
402 if (!(expr)) \
403 return setError (E_INVALIDARG, \
404 tr ("Argument %s is invalid (must be %s)"), #arg, #expr); \
405 } while (0)
406
407/**
408 * Checks that the given expression (that must involve the argument) is true and
409 * returns E_INVALIDARG + extended error info on failure. The error message must
410 * be customized.
411 * @param arg Argument.
412 * @param expr Expression to evaluate.
413 * @param msg Parenthesized printf-like expression (must start with a verb,
414 * like "must be one of...", "is not within...").
415 */
416#define CheckComArgExprMsg(arg, expr, msg) \
417 do { \
418 if (!(expr)) \
419 return setError (E_INVALIDARG, tr ("Argument %s %s"), \
420 #arg, Utf8StrFmt msg .raw()); \
421 } while (0)
422
423/**
424 * Checks that the given pointer to an output argument is valid and returns
425 * E_POINTER + extended error info otherwise.
426 * @param arg Pointer argument.
427 */
428#define CheckComArgOutPointerValid(arg) \
429 do { \
430 if (!VALID_PTR (arg)) \
431 return setError (E_POINTER, \
432 tr ("Output argument %s points to invalid memory location (%p)"), \
433 #arg, (void *) (arg)); \
434 } while (0)
435
436/**
437 * Checks that the given pointer to an output safe array argument is valid and
438 * returns E_POINTER + extended error info otherwise.
439 * @param arg Safe array argument.
440 */
441#define CheckComArgOutSafeArrayPointerValid(arg) \
442 do { \
443 if (ComSafeArrayOutIsNull (arg)) \
444 return setError (E_POINTER, \
445 tr ("Output argument %s points to invalid memory location (%p)"), \
446 #arg, (void *) (arg)); \
447 } while (0)
448
449/**
450 * Sets the extended error info and returns E_NOTIMPL.
451 */
452#define ReturnComNotImplemented() \
453 do { \
454 return setError (E_NOTIMPL, tr ("Method %s is not implemented"), __FUNCTION__); \
455 } while (0)
456
457////////////////////////////////////////////////////////////////////////////////
458
459/// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
460/**
461 * Checks whether this object is ready or not. Objects are typically ready
462 * after they are successfully created by their parent objects and become
463 * not ready when the respective parent itself becomes not ready or gets
464 * destroyed while a reference to the child is still held by the caller
465 * (which prevents it from destruction).
466 *
467 * When this object is not ready, the macro sets error info and returns
468 * E_ACCESSDENIED (the translatable error message is defined in null context).
469 * Otherwise, the macro does nothing.
470 *
471 * This macro <b>must</b> be used at the beginning of all interface methods
472 * (right after entering the class lock) in classes derived from both
473 * VirtualBoxBase and VirtualBoxSupportErrorInfoImpl.
474 */
475#define CHECK_READY() \
476 do { \
477 if (!isReady()) \
478 return setError (E_ACCESSDENIED, tr ("The object is not ready")); \
479 } while (0)
480
481/**
482 * Declares an empty constructor and destructor for the given class.
483 * This is useful to prevent the compiler from generating the default
484 * ctor and dtor, which in turn allows to use forward class statements
485 * (instead of including their header files) when declaring data members of
486 * non-fundamental types with constructors (which are always called implicitly
487 * by constructors and by the destructor of the class).
488 *
489 * This macro is to be placed within (the public section of) the class
490 * declaration. Its counterpart, DEFINE_EMPTY_CTOR_DTOR, must be placed
491 * somewhere in one of the translation units (usually .cpp source files).
492 *
493 * @param cls class to declare a ctor and dtor for
494 */
495#define DECLARE_EMPTY_CTOR_DTOR(cls) cls(); ~cls();
496
497/**
498 * Defines an empty constructor and destructor for the given class.
499 * See DECLARE_EMPTY_CTOR_DTOR for more info.
500 */
501#define DEFINE_EMPTY_CTOR_DTOR(cls) \
502 cls::cls () {}; cls::~cls () {};
503
504////////////////////////////////////////////////////////////////////////////////
505
506namespace stdx
507{
508 /**
509 * A wrapper around the container that owns pointers it stores.
510 *
511 * @note
512 * Ownership is recognized only when destructing the container!
513 * Pointers are not deleted when erased using erase() etc.
514 *
515 * @param container
516 * class that meets Container requirements (for example, an instance of
517 * std::list<>, std::vector<> etc.). The given class must store
518 * pointers (for example, std::list <MyType *>).
519 */
520 template <typename container>
521 class ptr_container : public container
522 {
523 public:
524 ~ptr_container()
525 {
526 for (typename container::iterator it = container::begin();
527 it != container::end();
528 ++ it)
529 delete (*it);
530 }
531 };
532}
533
534////////////////////////////////////////////////////////////////////////////////
535
536/**
537 * Abstract base class for all component classes implementing COM
538 * interfaces of the VirtualBox COM library.
539 *
540 * Declares functionality that should be available in all components.
541 *
542 * Note that this class is always subclassed using the virtual keyword so
543 * that only one instance of its VTBL and data is present in each derived class
544 * even in case if VirtualBoxBaseProto appears more than once among base classes
545 * of the particular component as a result of multiple inheritance.
546 *
547 * This makes it possible to have intermediate base classes used by several
548 * components that implement some common interface functionality but still let
549 * the final component classes choose what VirtualBoxBase variant it wants to
550 * use.
551 *
552 * Among the basic functionality implemented by this class is the primary object
553 * state that indicates if the object is ready to serve the calls, and if not,
554 * what stage it is currently at. Here is the primary state diagram:
555 *
556 * +-------------------------------------------------------+
557 * | |
558 * | (InitFailed) -----------------------+ |
559 * | ^ | |
560 * v | v |
561 * [*] ---> NotReady ----> (InInit) -----> Ready -----> (InUninit) ----+
562 * ^ | ^ | ^
563 * | v | v |
564 * | Limited | (MayUninit) --> (WillUninit)
565 * | | | |
566 * +-------+ +-------+
567 *
568 * The object is fully operational only when its state is Ready. The Limited
569 * state means that only some vital part of the object is operational, and it
570 * requires some sort of reinitialization to become fully operational. The
571 * NotReady state means the object is basically dead: it either was not yet
572 * initialized after creation at all, or was uninitialized and is waiting to be
573 * destroyed when the last reference to it is released. All other states are
574 * transitional.
575 *
576 * The NotReady->InInit->Ready, NotReady->InInit->Limited and
577 * NotReady->InInit->InitFailed transition is done by the AutoInitSpan smart
578 * class.
579 *
580 * The Limited->InInit->Ready, Limited->InInit->Limited and
581 * Limited->InInit->InitFailed transition is done by the AutoReinitSpan smart
582 * class.
583 *
584 * The Ready->InUninit->NotReady, InitFailed->InUninit->NotReady and
585 * WillUninit->InUninit->NotReady transitions are done by the AutoUninitSpan
586 * smart class.
587 *
588 * The Ready->MayUninit->Ready and Ready->MayUninit->WillUninit transitions are
589 * done by the AutoMayUninitSpan smart class.
590 *
591 * In order to maintain the primary state integrity and declared functionality
592 * all subclasses must:
593 *
594 * 1) Use the above Auto*Span classes to perform state transitions. See the
595 * individual class descriptions for details.
596 *
597 * 2) All public methods of subclasses (i.e. all methods that can be called
598 * directly, not only from within other methods of the subclass) must have a
599 * standard prolog as described in the AutoCaller and AutoLimitedCaller
600 * documentation. Alternatively, they must use addCaller()/releaseCaller()
601 * directly (and therefore have both the prolog and the epilog), but this is
602 * not recommended.
603 */
604class ATL_NO_VTABLE VirtualBoxBaseProto : public Lockable
605{
606public:
607
608 enum State { NotReady, Ready, InInit, InUninit, InitFailed, Limited,
609 MayUninit, WillUninit };
610
611protected:
612
613 VirtualBoxBaseProto();
614 virtual ~VirtualBoxBaseProto();
615
616public:
617
618 // util::Lockable interface
619 virtual RWLockHandle *lockHandle() const;
620
621 /**
622 * Unintialization method.
623 *
624 * Must be called by all final implementations (component classes) when the
625 * last reference to the object is released, before calling the destructor.
626 *
627 * This method is also automatically called by the uninit() method of this
628 * object's parent if this object is a dependent child of a class derived
629 * from VirtualBoxBaseWithChildren (see
630 * VirtualBoxBaseWithChildren::addDependentChild).
631 *
632 * @note Never call this method the AutoCaller scope or after the
633 * #addCaller() call not paired by #releaseCaller() because it is a
634 * guaranteed deadlock. See AutoUninitSpan for details.
635 */
636 virtual void uninit() {}
637
638 virtual HRESULT addCaller (State *aState = NULL, bool aLimited = false);
639 virtual void releaseCaller();
640
641 /**
642 * Adds a limited caller. This method is equivalent to doing
643 * <tt>addCaller (aState, true)</tt>, but it is preferred because provides
644 * better self-descriptiveness. See #addCaller() for more info.
645 */
646 HRESULT addLimitedCaller (State *aState = NULL)
647 {
648 return addCaller (aState, true /* aLimited */);
649 }
650
651 /**
652 * Smart class that automatically increases the number of callers of the
653 * given VirtualBoxBase object when an instance is constructed and decreases
654 * it back when the created instance goes out of scope (i.e. gets destroyed).
655 *
656 * If #rc() returns a failure after the instance creation, it means that
657 * the managed VirtualBoxBase object is not Ready, or in any other invalid
658 * state, so that the caller must not use the object and can return this
659 * failed result code to the upper level.
660 *
661 * See VirtualBoxBase::addCaller(), VirtualBoxBase::addLimitedCaller() and
662 * VirtualBoxBase::releaseCaller() for more details about object callers.
663 *
664 * @param aLimited |false| if this template should use
665 * VirtualiBoxBase::addCaller() calls to add callers, or
666 * |true| if VirtualiBoxBase::addLimitedCaller() should be
667 * used.
668 *
669 * @note It is preferable to use the AutoCaller and AutoLimitedCaller
670 * classes than specify the @a aLimited argument, for better
671 * self-descriptiveness.
672 */
673 template <bool aLimited>
674 class AutoCallerBase
675 {
676 public:
677
678 /**
679 * Increases the number of callers of the given object by calling
680 * VirtualBoxBase::addCaller().
681 *
682 * @param aObj Object to add a caller to. If NULL, this
683 * instance is effectively turned to no-op (where
684 * rc() will return S_OK and state() will be
685 * NotReady).
686 */
687 AutoCallerBase (VirtualBoxBaseProto *aObj)
688 : mObj (aObj)
689 , mRC (S_OK)
690 , mState (NotReady)
691 {
692 if (mObj)
693 mRC = mObj->addCaller (&mState, aLimited);
694 }
695
696 /**
697 * If the number of callers was successfully increased, decreases it
698 * using VirtualBoxBase::releaseCaller(), otherwise does nothing.
699 */
700 ~AutoCallerBase()
701 {
702 if (mObj && SUCCEEDED (mRC))
703 mObj->releaseCaller();
704 }
705
706 /**
707 * Stores the result code returned by VirtualBoxBase::addCaller() after
708 * instance creation or after the last #add() call. A successful result
709 * code means the number of callers was successfully increased.
710 */
711 HRESULT rc() const { return mRC; }
712
713 /**
714 * Returns |true| if |SUCCEEDED (rc())| is |true|, for convenience.
715 * |true| means the number of callers was successfully increased.
716 */
717 bool isOk() const { return SUCCEEDED (mRC); }
718
719 /**
720 * Stores the object state returned by VirtualBoxBase::addCaller() after
721 * instance creation or after the last #add() call.
722 */
723 State state() const { return mState; }
724
725 /**
726 * Temporarily decreases the number of callers of the managed object.
727 * May only be called if #isOk() returns |true|. Note that #rc() will
728 * return E_FAIL after this method succeeds.
729 */
730 void release()
731 {
732 Assert (SUCCEEDED (mRC));
733 if (SUCCEEDED (mRC))
734 {
735 if (mObj)
736 mObj->releaseCaller();
737 mRC = E_FAIL;
738 }
739 }
740
741 /**
742 * Restores the number of callers decreased by #release(). May only be
743 * called after #release().
744 */
745 void add()
746 {
747 Assert (!SUCCEEDED (mRC));
748 if (mObj && !SUCCEEDED (mRC))
749 mRC = mObj->addCaller (&mState, aLimited);
750 }
751
752 /**
753 * Attaches another object to this caller instance.
754 * The previous object's caller is released before the new one is added.
755 *
756 * @param aObj New object to attach, may be @c NULL.
757 */
758 void attach (VirtualBoxBaseProto *aObj)
759 {
760 /* detect simple self-reattachment */
761 if (mObj != aObj)
762 {
763 if (mObj && SUCCEEDED (mRC))
764 release();
765 mObj = aObj;
766 add();
767 }
768 }
769
770 /** Verbose equivalent to <tt>attach (NULL)</tt>. */
771 void detach() { attach (NULL); }
772
773 private:
774
775 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (AutoCallerBase)
776 DECLARE_CLS_NEW_DELETE_NOOP (AutoCallerBase)
777
778 VirtualBoxBaseProto *mObj;
779 HRESULT mRC;
780 State mState;
781 };
782
783 /**
784 * Smart class that automatically increases the number of normal
785 * (non-limited) callers of the given VirtualBoxBase object when an instance
786 * is constructed and decreases it back when the created instance goes out
787 * of scope (i.e. gets destroyed).
788 *
789 * A typical usage pattern to declare a normal method of some object (i.e. a
790 * method that is valid only when the object provides its full
791 * functionality) is:
792 * <code>
793 * STDMETHODIMP Component::Foo()
794 * {
795 * AutoCaller autoCaller (this);
796 * CheckComRCReturnRC (autoCaller.rc());
797 * ...
798 * </code>
799 *
800 * Using this class is equivalent to using the AutoCallerBase template with
801 * the @a aLimited argument set to |false|, but this class is preferred
802 * because provides better self-descriptiveness.
803 *
804 * See AutoCallerBase for more information about auto caller functionality.
805 */
806 typedef AutoCallerBase <false> AutoCaller;
807
808 /**
809 * Smart class that automatically increases the number of limited callers of
810 * the given VirtualBoxBase object when an instance is constructed and
811 * decreases it back when the created instance goes out of scope (i.e. gets
812 * destroyed).
813 *
814 * A typical usage pattern to declare a limited method of some object (i.e.
815 * a method that is valid even if the object doesn't provide its full
816 * functionality) is:
817 * <code>
818 * STDMETHODIMP Component::Bar()
819 * {
820 * AutoLimitedCaller autoCaller (this);
821 * CheckComRCReturnRC (autoCaller.rc());
822 * ...
823 * </code>
824 *
825 * Using this class is equivalent to using the AutoCallerBase template with
826 * the @a aLimited argument set to |true|, but this class is preferred
827 * because provides better self-descriptiveness.
828 *
829 * See AutoCallerBase for more information about auto caller functionality.
830 */
831 typedef AutoCallerBase <true> AutoLimitedCaller;
832
833protected:
834
835 /**
836 * Smart class to enclose the state transition NotReady->InInit->Ready.
837 *
838 * The purpose of this span is to protect object initialization.
839 *
840 * Instances must be created as a stack-based variable taking |this| pointer
841 * as the argument at the beginning of init() methods of VirtualBoxBase
842 * subclasses. When this variable is created it automatically places the
843 * object to the InInit state.
844 *
845 * When the created variable goes out of scope (i.e. gets destroyed) then,
846 * depending on the result status of this initialization span, it either
847 * places the object to Ready or Limited state or calls the object's
848 * VirtualBoxBase::uninit() method which is supposed to place the object
849 * back to the NotReady state using the AutoUninitSpan class.
850 *
851 * The initial result status of the initialization span is determined by the
852 * @a aResult argument of the AutoInitSpan constructor (Result::Failed by
853 * default). Inside the initialization span, the success status can be set
854 * to Result::Succeeded using #setSucceeded(), to to Result::Limited using
855 * #setLimited() or to Result::Failed using #setFailed(). Please don't
856 * forget to set the correct success status before getting the AutoInitSpan
857 * variable destroyed (for example, by performing an early return from
858 * the init() method)!
859 *
860 * Note that if an instance of this class gets constructed when the object
861 * is in the state other than NotReady, #isOk() returns |false| and methods
862 * of this class do nothing: the state transition is not performed.
863 *
864 * A typical usage pattern is:
865 * <code>
866 * HRESULT Component::init()
867 * {
868 * AutoInitSpan autoInitSpan (this);
869 * AssertReturn (autoInitSpan.isOk(), E_FAIL);
870 * ...
871 * if (FAILED (rc))
872 * return rc;
873 * ...
874 * if (SUCCEEDED (rc))
875 * autoInitSpan.setSucceeded();
876 * return rc;
877 * }
878 * </code>
879 *
880 * @note Never create instances of this class outside init() methods of
881 * VirtualBoxBase subclasses and never pass anything other than |this|
882 * as the argument to the constructor!
883 */
884 class AutoInitSpan
885 {
886 public:
887
888 enum Result { Failed = 0x0, Succeeded = 0x1, Limited = 0x2 };
889
890 AutoInitSpan (VirtualBoxBaseProto *aObj, Result aResult = Failed);
891 ~AutoInitSpan();
892
893 /**
894 * Returns |true| if this instance has been created at the right moment
895 * (when the object was in the NotReady state) and |false| otherwise.
896 */
897 bool isOk() const { return mOk; }
898
899 /**
900 * Sets the initialization status to Succeeded to indicates successful
901 * initialization. The AutoInitSpan destructor will place the managed
902 * VirtualBoxBase object to the Ready state.
903 */
904 void setSucceeded() { mResult = Succeeded; }
905
906 /**
907 * Sets the initialization status to Succeeded to indicate limited
908 * (partly successful) initialization. The AutoInitSpan destructor will
909 * place the managed VirtualBoxBase object to the Limited state.
910 */
911 void setLimited() { mResult = Limited; }
912
913 /**
914 * Sets the initialization status to Failure to indicates failed
915 * initialization. The AutoInitSpan destructor will place the managed
916 * VirtualBoxBase object to the InitFailed state and will automatically
917 * call its uninit() method which is supposed to place the object back
918 * to the NotReady state using AutoUninitSpan.
919 */
920 void setFailed() { mResult = Failed; }
921
922 /** Returns the current initialization result. */
923 Result result() { return mResult; }
924
925 private:
926
927 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (AutoInitSpan)
928 DECLARE_CLS_NEW_DELETE_NOOP (AutoInitSpan)
929
930 VirtualBoxBaseProto *mObj;
931 Result mResult : 3; // must be at least total number of bits + 1 (sign)
932 bool mOk : 1;
933 };
934
935 /**
936 * Smart class to enclose the state transition Limited->InInit->Ready.
937 *
938 * The purpose of this span is to protect object re-initialization.
939 *
940 * Instances must be created as a stack-based variable taking |this| pointer
941 * as the argument at the beginning of methods of VirtualBoxBase
942 * subclasses that try to re-initialize the object to bring it to the Ready
943 * state (full functionality) after partial initialization (limited
944 * functionality). When this variable is created, it automatically places
945 * the object to the InInit state.
946 *
947 * When the created variable goes out of scope (i.e. gets destroyed),
948 * depending on the success status of this initialization span, it either
949 * places the object to the Ready state or brings it back to the Limited
950 * state.
951 *
952 * The initial success status of the re-initialization span is |false|. In
953 * order to make it successful, #setSucceeded() must be called before the
954 * instance is destroyed.
955 *
956 * Note that if an instance of this class gets constructed when the object
957 * is in the state other than Limited, #isOk() returns |false| and methods
958 * of this class do nothing: the state transition is not performed.
959 *
960 * A typical usage pattern is:
961 * <code>
962 * HRESULT Component::reinit()
963 * {
964 * AutoReinitSpan autoReinitSpan (this);
965 * AssertReturn (autoReinitSpan.isOk(), E_FAIL);
966 * ...
967 * if (FAILED (rc))
968 * return rc;
969 * ...
970 * if (SUCCEEDED (rc))
971 * autoReinitSpan.setSucceeded();
972 * return rc;
973 * }
974 * </code>
975 *
976 * @note Never create instances of this class outside re-initialization
977 * methods of VirtualBoxBase subclasses and never pass anything other than
978 * |this| as the argument to the constructor!
979 */
980 class AutoReinitSpan
981 {
982 public:
983
984 AutoReinitSpan (VirtualBoxBaseProto *aObj);
985 ~AutoReinitSpan();
986
987 /**
988 * Returns |true| if this instance has been created at the right moment
989 * (when the object was in the Limited state) and |false| otherwise.
990 */
991 bool isOk() const { return mOk; }
992
993 /**
994 * Sets the re-initialization status to Succeeded to indicates
995 * successful re-initialization. The AutoReinitSpan destructor will place
996 * the managed VirtualBoxBase object to the Ready state.
997 */
998 void setSucceeded() { mSucceeded = true; }
999
1000 private:
1001
1002 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (AutoReinitSpan)
1003 DECLARE_CLS_NEW_DELETE_NOOP (AutoReinitSpan)
1004
1005 VirtualBoxBaseProto *mObj;
1006 bool mSucceeded : 1;
1007 bool mOk : 1;
1008 };
1009
1010 /**
1011 * Smart class to enclose the state transition Ready->InUnnit->NotReady,
1012 * InitFailed->InUnnit->NotReady or WillUninit->InUnnit->NotReady.
1013 *
1014 * The purpose of this span is to protect object uninitialization.
1015 *
1016 * Instances must be created as a stack-based variable taking |this| pointer
1017 * as the argument at the beginning of uninit() methods of VirtualBoxBase
1018 * subclasses. When this variable is created it automatically places the
1019 * object to the InUninit state, unless it is already in the NotReady state
1020 * as indicated by #uninitDone() returning |true|. In the latter case, the
1021 * uninit() method must immediately return because there should be nothing
1022 * to uninitialize.
1023 *
1024 * When this variable goes out of scope (i.e. gets destroyed), it places the
1025 * object to NotReady state.
1026 *
1027 * A typical usage pattern is:
1028 * <code>
1029 * void Component::uninit()
1030 * {
1031 * AutoUninitSpan autoUninitSpan (this);
1032 * if (autoUninitSpan.uninitDone())
1033 * return;
1034 * ...
1035 * }
1036 * </code>
1037 *
1038 * @note The constructor of this class blocks the current thread execution
1039 * until the number of callers added to the object using #addCaller()
1040 * or AutoCaller drops to zero. For this reason, it is forbidden to
1041 * create instances of this class (or call uninit()) within the
1042 * AutoCaller or #addCaller() scope because it is a guaranteed
1043 * deadlock.
1044 *
1045 * @note Never create instances of this class outside uninit() methods and
1046 * never pass anything other than |this| as the argument to the
1047 * constructor!
1048 */
1049 class AutoUninitSpan
1050 {
1051 public:
1052
1053 AutoUninitSpan (VirtualBoxBaseProto *aObj);
1054 ~AutoUninitSpan();
1055
1056 /** |true| when uninit() is called as a result of init() failure */
1057 bool initFailed() { return mInitFailed; }
1058
1059 /** |true| when uninit() has already been called (so the object is NotReady) */
1060 bool uninitDone() { return mUninitDone; }
1061
1062 private:
1063
1064 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (AutoUninitSpan)
1065 DECLARE_CLS_NEW_DELETE_NOOP (AutoUninitSpan)
1066
1067 VirtualBoxBaseProto *mObj;
1068 bool mInitFailed : 1;
1069 bool mUninitDone : 1;
1070 };
1071
1072 /**
1073 * Smart class to enclose the state transition Ready->MayUninit->NotReady or
1074 * Ready->MayUninit->WillUninit.
1075 *
1076 * The purpose of this span is to safely check if unintialization is
1077 * possible at the given moment and seamlessly perform it if so.
1078 *
1079 * Instances must be created as a stack-based variable taking |this| pointer
1080 * as the argument at the beginning of methods of VirtualBoxBase
1081 * subclasses that want to uninitialize the object if a necessary set of
1082 * criteria is met and leave it Ready otherwise.
1083 *
1084 * When this variable is created it automatically places the object to the
1085 * MayUninit state if it is Ready, does nothing but returns |true| in
1086 * response to #alreadyInProgress() if it is already in MayUninit, or
1087 * returns a failure in response to #rc() in any other case. The example
1088 * below shows how the user must react in latter two cases.
1089 *
1090 * When this variable goes out of scope (i.e. gets destroyed), it places the
1091 * object back to Ready state unless #acceptUninit() is called in which case
1092 * the object is placed to WillUninit state and uninit() is immediately
1093 * called after that.
1094 *
1095 * A typical usage pattern is:
1096 * <code>
1097 * void Component::uninit()
1098 * {
1099 * AutoMayUninitSpan mayUninitSpan (this);
1100 * CheckComRCReturnRC (mayUninitSpan.rc());
1101 * if (mayUninitSpan.alreadyInProgress())
1102 * return S_OK;
1103 * ...
1104 * if (FAILED (rc))
1105 * return rc; // will go back to Ready
1106 * ...
1107 * if (SUCCEEDED (rc))
1108 * mayUninitSpan.acceptUninit(); // will call uninit()
1109 * return rc;
1110 * }
1111 * </code>
1112 *
1113 * @note The constructor of this class blocks the current thread execution
1114 * until the number of callers added to the object using #addCaller()
1115 * or AutoCaller drops to zero. For this reason, it is forbidden to
1116 * create instances of this class (or call uninit()) within the
1117 * AutoCaller or #addCaller() scope because it is a guaranteed
1118 * deadlock.
1119 */
1120 class AutoMayUninitSpan
1121 {
1122 public:
1123
1124 AutoMayUninitSpan (VirtualBoxBaseProto *aObj);
1125 ~AutoMayUninitSpan();
1126
1127 /**
1128 * Returns a failure if the AutoMayUninitSpan variable was constructed
1129 * at an improper time. If there is a failure, do nothing but return
1130 * it to the caller.
1131 */
1132 HRESULT rc() { return mRC; }
1133
1134 /**
1135 * Returns |true| if AutoMayUninitSpan is already in progress on some
1136 * other thread. If it's the case, do nothing but return S_OK to
1137 * the caller.
1138 */
1139 bool alreadyInProgress() { return mAlreadyInProgress; }
1140
1141 /*
1142 * Accepts uninitialization and causes the destructor to go to
1143 * WillUninit state and call uninit() afterwards.
1144 */
1145 void acceptUninit() { mAcceptUninit = true; }
1146
1147 private:
1148
1149 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (AutoMayUninitSpan)
1150 DECLARE_CLS_NEW_DELETE_NOOP (AutoMayUninitSpan)
1151
1152 VirtualBoxBaseProto *mObj;
1153
1154 HRESULT mRC;
1155 bool mAlreadyInProgress : 1;
1156 bool mAcceptUninit : 1;
1157 };
1158
1159 /**
1160 * Returns a lock handle used to protect the primary state fields (used by
1161 * #addCaller(), AutoInitSpan, AutoUninitSpan, etc.). Only intended to be
1162 * used for similar purposes in subclasses. WARNING: NO any other locks may
1163 * be requested while holding this lock!
1164 */
1165 WriteLockHandle *stateLockHandle() { return &mStateLock; }
1166
1167private:
1168
1169 void setState (State aState)
1170 {
1171 Assert (mState != aState);
1172 mState = aState;
1173 mStateChangeThread = RTThreadSelf();
1174 }
1175
1176 /** Primary state of this object */
1177 State mState;
1178 /** Thread that caused the last state change */
1179 RTTHREAD mStateChangeThread;
1180 /** Total number of active calls to this object */
1181 unsigned mCallers;
1182 /** Posted when the number of callers drops to zero */
1183 RTSEMEVENT mZeroCallersSem;
1184 /** Posted when the object goes from InInit/InUninit to some other state */
1185 RTSEMEVENTMULTI mInitUninitSem;
1186 /** Number of threads waiting for mInitUninitDoneSem */
1187 unsigned mInitUninitWaiters;
1188
1189 /** Protects access to state related data members */
1190 WriteLockHandle mStateLock;
1191
1192 /** User-level object lock for subclasses */
1193 mutable RWLockHandle *mObjectLock;
1194};
1195
1196////////////////////////////////////////////////////////////////////////////////
1197
1198/**
1199 * This macro adds the error info support to methods of the VirtualBoxBase
1200 * class (by overriding them). Place it to the public section of the
1201 * VirtualBoxBase subclass and the following methods will set the extended
1202 * error info in case of failure instead of just returning the result code:
1203 *
1204 * <ul>
1205 * <li>VirtualBoxBase::addCaller()
1206 * </ul>
1207 *
1208 * @note The given VirtualBoxBase subclass must also inherit from both
1209 * VirtualBoxSupportErrorInfoImpl and VirtualBoxSupportTranslation templates!
1210 *
1211 * @param C VirtualBoxBase subclass to add the error info support to
1212 */
1213#define VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(C) \
1214 virtual HRESULT addCaller (VirtualBoxBaseProto::State *aState = NULL, \
1215 bool aLimited = false) \
1216 { \
1217 VirtualBoxBaseProto::State state; \
1218 HRESULT rc = VirtualBoxBaseProto::addCaller (&state, aLimited); \
1219 if (FAILED (rc)) \
1220 { \
1221 if (state == VirtualBoxBaseProto::Limited) \
1222 rc = setError (rc, tr ("The object functionality is limited")); \
1223 else \
1224 rc = setError (rc, tr ("The object is not ready")); \
1225 } \
1226 if (aState) \
1227 *aState = state; \
1228 return rc; \
1229 } \
1230
1231////////////////////////////////////////////////////////////////////////////////
1232
1233/// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
1234class ATL_NO_VTABLE VirtualBoxBase
1235 : virtual public VirtualBoxBaseProto
1236#if !defined (VBOX_WITH_XPCOM)
1237 , public CComObjectRootEx <CComMultiThreadModel>
1238#else
1239 , public CComObjectRootEx
1240#endif
1241{
1242
1243public:
1244 VirtualBoxBase()
1245 {
1246 mReady = false;
1247 }
1248 virtual ~VirtualBoxBase()
1249 {
1250 }
1251
1252 /**
1253 * Virtual unintialization method. Called during parent object's
1254 * uninitialization, if the given subclass instance is a dependent child of
1255 * a class derived from VirtualBoxBaseWithChildren (@sa
1256 * VirtualBoxBaseWithChildren::addDependentChild). In this case, this
1257 * method's implementation must call setReady (false),
1258 */
1259 virtual void uninit() {}
1260
1261
1262 // sets the ready state of the object
1263 void setReady(bool isReady)
1264 {
1265 mReady = isReady;
1266 }
1267 // get the ready state of the object
1268 bool isReady()
1269 {
1270 return mReady;
1271 }
1272
1273 static const char *translate (const char *context, const char *sourceText,
1274 const char *comment = 0);
1275
1276private:
1277
1278 // flag determining whether an object is ready
1279 // for usage, i.e. methods may be called
1280 bool mReady;
1281 // mutex semaphore to lock the object
1282};
1283
1284/**
1285 * Temporary class to disable deprecated methods of VirtualBoxBase.
1286 * Can be used as a base for components that are completely switched to
1287 * the new locking scheme (VirtualBoxBaseProto).
1288 *
1289 * @todo remove after we switch to VirtualBoxBaseNEXT completely.
1290 */
1291class VirtualBoxBaseNEXT : public VirtualBoxBase
1292{
1293private:
1294
1295 void lock();
1296 void unlock();
1297 void setReady (bool isReady);
1298 bool isReady();
1299};
1300
1301////////////////////////////////////////////////////////////////////////////////
1302
1303/** Helper for VirtualBoxSupportTranslation. */
1304class VirtualBoxSupportTranslationBase
1305{
1306protected:
1307 static bool cutClassNameFrom__PRETTY_FUNCTION__ (char *aPrettyFunctionName);
1308};
1309
1310/**
1311 * The VirtualBoxSupportTranslation template implements the NLS string
1312 * translation support for the given class.
1313 *
1314 * Translation support is provided by the static #tr() function. This function,
1315 * given a string in UTF-8 encoding, looks up for a translation of the given
1316 * string by calling the VirtualBoxBase::translate() global function which
1317 * receives the name of the enclosing class ("context of translation") as the
1318 * additional argument and returns a translated string based on the currently
1319 * active language.
1320 *
1321 * @param C Class that needs to support the string translation.
1322 *
1323 * @note Every class that wants to use the #tr() function in its own methods
1324 * must inherit from this template, regardless of whether its base class
1325 * (if any) inherits from it or not. Otherwise, the translation service
1326 * will not work correctly. However, the declaration of the derived
1327 * class must contain
1328 * the <tt>COM_SUPPORTTRANSLATION_OVERRIDE (<ClassName>)</tt> macro if one
1329 * of its base classes also inherits from this template (to resolve the
1330 * ambiguity of the #tr() function).
1331 */
1332template <class C>
1333class VirtualBoxSupportTranslation : virtual protected VirtualBoxSupportTranslationBase
1334{
1335public:
1336
1337 /**
1338 * Translates the given text string by calling VirtualBoxBase::translate()
1339 * and passing the name of the C class as the first argument ("context of
1340 * translation") See VirtualBoxBase::translate() for more info.
1341 *
1342 * @param aSourceText String to translate.
1343 * @param aComment Comment to the string to resolve possible
1344 * ambiguities (NULL means no comment).
1345 *
1346 * @return Translated version of the source string in UTF-8 encoding, or
1347 * the source string itself if the translation is not found in the
1348 * specified context.
1349 */
1350 inline static const char *tr (const char *aSourceText,
1351 const char *aComment = NULL)
1352 {
1353 return VirtualBoxBase::translate (className(), aSourceText, aComment);
1354 }
1355
1356protected:
1357
1358 static const char *className()
1359 {
1360 static char fn [sizeof (__PRETTY_FUNCTION__) + 1];
1361 if (!sClassName)
1362 {
1363 strcpy (fn, __PRETTY_FUNCTION__);
1364 cutClassNameFrom__PRETTY_FUNCTION__ (fn);
1365 sClassName = fn;
1366 }
1367 return sClassName;
1368 }
1369
1370private:
1371
1372 static const char *sClassName;
1373};
1374
1375template <class C>
1376const char *VirtualBoxSupportTranslation <C>::sClassName = NULL;
1377
1378/**
1379 * This macro must be invoked inside the public section of the declaration of
1380 * the class inherited from the VirtualBoxSupportTranslation template in case
1381 * if one of its other base classes also inherits from that template. This is
1382 * necessary to resolve the ambiguity of the #tr() function.
1383 *
1384 * @param C Class that inherits the VirtualBoxSupportTranslation template
1385 * more than once (through its other base clases).
1386 */
1387#define VIRTUALBOXSUPPORTTRANSLATION_OVERRIDE(C) \
1388 inline static const char *tr (const char *aSourceText, \
1389 const char *aComment = NULL) \
1390 { \
1391 return VirtualBoxSupportTranslation <C>::tr (aSourceText, aComment); \
1392 }
1393
1394/**
1395 * Dummy macro that is used to shut down Qt's lupdate tool warnings in some
1396 * situations. This macro needs to be present inside (better at the very
1397 * beginning) of the declaration of the class that inherits from
1398 * VirtualBoxSupportTranslation template, to make lupdate happy.
1399 */
1400#define Q_OBJECT
1401
1402////////////////////////////////////////////////////////////////////////////////
1403
1404/**
1405 * Helper for the VirtualBoxSupportErrorInfoImpl template.
1406 */
1407/// @todo switch to com::SupportErrorInfo* and remove
1408class VirtualBoxSupportErrorInfoImplBase
1409{
1410 static HRESULT setErrorInternal (HRESULT aResultCode, const GUID &aIID,
1411 const Bstr &aComponent, const Bstr &aText,
1412 bool aWarning, bool aLogIt);
1413
1414protected:
1415
1416 /**
1417 * The MultiResult class is a com::FWResult enhancement that also acts as a
1418 * switch to turn on multi-error mode for #setError() or #setWarning()
1419 * calls.
1420 *
1421 * When an instance of this class is created, multi-error mode is turned on
1422 * for the current thread and the turn-on counter is increased by one. In
1423 * multi-error mode, a call to #setError() or #setWarning() does not
1424 * overwrite the current error or warning info object possibly set on the
1425 * current thread by other method calls, but instead it stores this old
1426 * object in the IVirtualBoxErrorInfo::next attribute of the new error
1427 * object being set.
1428 *
1429 * This way, error/warning objects are stacked together and form a chain of
1430 * errors where the most recent error is the first one retrieved by the
1431 * calling party, the preceding error is what the
1432 * IVirtualBoxErrorInfo::next attribute of the first error points to, and so
1433 * on, up to the first error or warning occurred which is the last in the
1434 * chain. See IVirtualBoxErrorInfo documentation for more info.
1435 *
1436 * When the instance of the MultiResult class goes out of scope and gets
1437 * destroyed, it automatically decreases the turn-on counter by one. If
1438 * the counter drops to zero, multi-error mode for the current thread is
1439 * turned off and the thread switches back to single-error mode where every
1440 * next error or warning object overwrites the previous one.
1441 *
1442 * Note that the caller of a COM method uses a non-S_OK result code to
1443 * decide if the method has returned an error (negative codes) or a warning
1444 * (positive non-zero codes) and will query extended error info only in
1445 * these two cases. However, since multi-error mode implies that the method
1446 * doesn't return control return to the caller immediately after the first
1447 * error or warning but continues its execution, the functionality provided
1448 * by the base com::FWResult class becomes very useful because it allows to
1449 * preserve the error or the warning result code even if it is later assigned
1450 * a S_OK value multiple times. See com::FWResult for details.
1451 *
1452 * Here is the typical usage pattern:
1453 * <code>
1454
1455 HRESULT Bar::method()
1456 {
1457 // assume multi-errors are turned off here...
1458
1459 if (something)
1460 {
1461 // Turn on multi-error mode and make sure severity is preserved
1462 MultiResult rc = foo->method1();
1463
1464 // return on fatal error, but continue on warning or on success
1465 CheckComRCReturnRC (rc);
1466
1467 rc = foo->method2();
1468 // no matter what result, stack it and continue
1469
1470 // ...
1471
1472 // return the last worst result code (it will be preserved even if
1473 // foo->method2() returns S_OK.
1474 return rc;
1475 }
1476
1477 // multi-errors are turned off here again...
1478
1479 return S_OK;
1480 }
1481
1482 * </code>
1483 *
1484 *
1485 * @note This class is intended to be instantiated on the stack, therefore
1486 * You cannot create them using new(). Although it is possible to copy
1487 * instances of MultiResult or return them by value, please never do
1488 * that as it is breaks the class semantics (and will assert).
1489 */
1490 class MultiResult : public com::FWResult
1491 {
1492 public:
1493
1494 /**
1495 * @copydoc com::FWResult::FWResult().
1496 */
1497 MultiResult (HRESULT aRC = E_FAIL) : FWResult (aRC) { init(); }
1498
1499 MultiResult (const MultiResult &aThat) : FWResult (aThat)
1500 {
1501 /* We need this copy constructor only for GCC that wants to have
1502 * it in case of expressions like |MultiResult rc = E_FAIL;|. But
1503 * we assert since the optimizer should actually avoid the
1504 * temporary and call the other constructor directly instead. */
1505 AssertFailed();
1506 init();
1507 }
1508
1509 ~MultiResult();
1510
1511 MultiResult &operator= (HRESULT aRC)
1512 {
1513 com::FWResult::operator= (aRC);
1514 return *this;
1515 }
1516
1517 MultiResult &operator= (const MultiResult &aThat)
1518 {
1519 /* We need this copy constructor only for GCC that wants to have
1520 * it in case of expressions like |MultiResult rc = E_FAIL;|. But
1521 * we assert since the optimizer should actually avoid the
1522 * temporary and call the other constructor directly instead. */
1523 AssertFailed();
1524 com::FWResult::operator= (aThat);
1525 return *this;
1526 }
1527
1528 private:
1529
1530 DECLARE_CLS_NEW_DELETE_NOOP (MultiResult)
1531
1532 void init();
1533
1534 static RTTLS sCounter;
1535
1536 friend class VirtualBoxSupportErrorInfoImplBase;
1537 };
1538
1539 static HRESULT setError (HRESULT aResultCode, const GUID &aIID,
1540 const Bstr &aComponent,
1541 const Bstr &aText,
1542 bool aLogIt = true)
1543 {
1544 return setErrorInternal (aResultCode, aIID, aComponent, aText,
1545 false /* aWarning */, aLogIt);
1546 }
1547
1548 static HRESULT setWarning (HRESULT aResultCode, const GUID &aIID,
1549 const Bstr &aComponent,
1550 const Bstr &aText)
1551 {
1552 return setErrorInternal (aResultCode, aIID, aComponent, aText,
1553 true /* aWarning */, true /* aLogIt */);
1554 }
1555
1556 static HRESULT setError (HRESULT aResultCode, const GUID &aIID,
1557 const Bstr &aComponent,
1558 const char *aText, va_list aArgs, bool aLogIt = true)
1559 {
1560 return setErrorInternal (aResultCode, aIID, aComponent,
1561 Utf8StrFmtVA (aText, aArgs),
1562 false /* aWarning */, aLogIt);
1563 }
1564
1565 static HRESULT setWarning (HRESULT aResultCode, const GUID &aIID,
1566 const Bstr &aComponent,
1567 const char *aText, va_list aArgs)
1568 {
1569 return setErrorInternal (aResultCode, aIID, aComponent,
1570 Utf8StrFmtVA (aText, aArgs),
1571 true /* aWarning */, true /* aLogIt */);
1572 }
1573};
1574
1575/**
1576 * This template implements ISupportErrorInfo for the given component class
1577 * and provides the #setError() method to conveniently set the error information
1578 * from within interface methods' implementations.
1579 *
1580 * On Windows, the template argument must define a COM interface map using
1581 * BEGIN_COM_MAP / END_COM_MAP macros and this map must contain a
1582 * COM_INTERFACE_ENTRY(ISupportErrorInfo) definition. All interface entries
1583 * that follow it will be considered to support IErrorInfo, i.e. the
1584 * InterfaceSupportsErrorInfo() implementation will return S_OK for the
1585 * corresponding IID.
1586 *
1587 * On all platforms, the template argument must also define the following
1588 * method: |public static const wchar_t *C::getComponentName()|. See
1589 * #setError (HRESULT, const char *, ...) for a description on how it is
1590 * used.
1591 *
1592 * @param C
1593 * component class that implements one or more COM interfaces
1594 * @param I
1595 * default interface for the component. This interface's IID is used
1596 * by the shortest form of #setError, for convenience.
1597 */
1598/// @todo switch to com::SupportErrorInfo* and remove
1599template <class C, class I>
1600class ATL_NO_VTABLE VirtualBoxSupportErrorInfoImpl
1601 : protected VirtualBoxSupportErrorInfoImplBase
1602#if !defined (VBOX_WITH_XPCOM)
1603 , public ISupportErrorInfo
1604#else
1605#endif
1606{
1607public:
1608
1609#if !defined (VBOX_WITH_XPCOM)
1610 STDMETHOD(InterfaceSupportsErrorInfo) (REFIID riid)
1611 {
1612 const _ATL_INTMAP_ENTRY* pEntries = C::_GetEntries();
1613 Assert (pEntries);
1614 if (!pEntries)
1615 return S_FALSE;
1616
1617 BOOL bSupports = FALSE;
1618 BOOL bISupportErrorInfoFound = FALSE;
1619
1620 while (pEntries->pFunc != NULL && !bSupports)
1621 {
1622 if (!bISupportErrorInfoFound)
1623 {
1624 // skip the com map entries until ISupportErrorInfo is found
1625 bISupportErrorInfoFound =
1626 InlineIsEqualGUID (*(pEntries->piid), IID_ISupportErrorInfo);
1627 }
1628 else
1629 {
1630 // look for the requested interface in the rest of the com map
1631 bSupports = InlineIsEqualGUID (*(pEntries->piid), riid);
1632 }
1633 pEntries++;
1634 }
1635
1636 Assert (bISupportErrorInfoFound);
1637
1638 return bSupports ? S_OK : S_FALSE;
1639 }
1640#endif // !defined (VBOX_WITH_XPCOM)
1641
1642protected:
1643
1644 /**
1645 * Sets the error information for the current thread.
1646 * This information can be retrieved by a caller of an interface method
1647 * using IErrorInfo on Windows or nsIException on Linux, or the cross-platform
1648 * IVirtualBoxErrorInfo interface that provides extended error info (only
1649 * for components from the VirtualBox COM library). Alternatively, the
1650 * platform-independent class com::ErrorInfo (defined in VBox[XP]COM.lib)
1651 * can be used to retrieve error info in a convenient way.
1652 *
1653 * It is assumed that the interface method that uses this function returns
1654 * an unsuccessful result code to the caller (otherwise, there is no reason
1655 * for the caller to try to retrieve error info after method invocation).
1656 *
1657 * Here is a table of correspondence between this method's arguments
1658 * and IErrorInfo/nsIException/IVirtualBoxErrorInfo attributes/methods:
1659 *
1660 * argument IErrorInfo nsIException IVirtualBoxErrorInfo
1661 * ----------------------------------------------------------------
1662 * resultCode -- result resultCode
1663 * iid GetGUID -- interfaceID
1664 * component GetSource -- component
1665 * text GetDescription message text
1666 *
1667 * This method is rarely needs to be used though. There are more convenient
1668 * overloaded versions, that automatically substitute some arguments
1669 * taking their values from the template parameters. See
1670 * #setError (HRESULT, const char *, ...) for an example.
1671 *
1672 * @param aResultCode result (error) code, must not be S_OK
1673 * @param aIID IID of the interface that defines the error
1674 * @param aComponent name of the component that generates the error
1675 * @param aText error message (must not be null), an RTStrPrintf-like
1676 * format string in UTF-8 encoding
1677 * @param ... list of arguments for the format string
1678 *
1679 * @return
1680 * the error argument, for convenience, If an error occurs while
1681 * creating error info itself, that error is returned instead of the
1682 * error argument.
1683 */
1684 static HRESULT setError (HRESULT aResultCode, const GUID &aIID,
1685 const wchar_t *aComponent,
1686 const char *aText, ...)
1687 {
1688 va_list args;
1689 va_start (args, aText);
1690 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError
1691 (aResultCode, aIID, aComponent, aText, args, true /* aLogIt */);
1692 va_end (args);
1693 return rc;
1694 }
1695
1696 /**
1697 * This method is the same as #setError() except that it makes sure @a
1698 * aResultCode doesn't have the error severity bit (31) set when passed
1699 * down to the created IVirtualBoxErrorInfo object.
1700 *
1701 * The error severity bit is always cleared by this call, thereof you can
1702 * use ordinary E_XXX result code constants, for convenience. However, this
1703 * behavior may be non-standard on some COM platforms.
1704 */
1705 static HRESULT setWarning (HRESULT aResultCode, const GUID &aIID,
1706 const wchar_t *aComponent,
1707 const char *aText, ...)
1708 {
1709 va_list args;
1710 va_start (args, aText);
1711 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setWarning
1712 (aResultCode, aIID, aComponent, aText, args);
1713 va_end (args);
1714 return rc;
1715 }
1716
1717 /**
1718 * Sets the error information for the current thread.
1719 * A convenience method that automatically sets the default interface
1720 * ID (taken from the I template argument) and the component name
1721 * (a value of C::getComponentName()).
1722 *
1723 * See #setError (HRESULT, const GUID &, const wchar_t *, const char *text, ...)
1724 * for details.
1725 *
1726 * This method is the most common (and convenient) way to set error
1727 * information from within interface methods. A typical pattern of usage
1728 * is looks like this:
1729 *
1730 * <code>
1731 * return setError (E_FAIL, "Terrible Error");
1732 * </code>
1733 * or
1734 * <code>
1735 * HRESULT rc = setError (E_FAIL, "Terrible Error");
1736 * ...
1737 * return rc;
1738 * </code>
1739 */
1740 static HRESULT setError (HRESULT aResultCode, const char *aText, ...)
1741 {
1742 va_list args;
1743 va_start (args, aText);
1744 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError
1745 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText, args, true /* aLogIt */);
1746 va_end (args);
1747 return rc;
1748 }
1749
1750 /**
1751 * This method is the same as #setError() except that it makes sure @a
1752 * aResultCode doesn't have the error severity bit (31) set when passed
1753 * down to the created IVirtualBoxErrorInfo object.
1754 *
1755 * The error severity bit is always cleared by this call, thereof you can
1756 * use ordinary E_XXX result code constants, for convenience. However, this
1757 * behavior may be non-standard on some COM platforms.
1758 */
1759 static HRESULT setWarning (HRESULT aResultCode, const char *aText, ...)
1760 {
1761 va_list args;
1762 va_start (args, aText);
1763 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setWarning
1764 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText, args);
1765 va_end (args);
1766 return rc;
1767 }
1768
1769 /**
1770 * Sets the error information for the current thread, va_list variant.
1771 * A convenience method that automatically sets the default interface
1772 * ID (taken from the I template argument) and the component name
1773 * (a value of C::getComponentName()).
1774 *
1775 * See #setError (HRESULT, const GUID &, const wchar_t *, const char *text, ...)
1776 * and #setError (HRESULT, const char *, ...) for details.
1777 */
1778 static HRESULT setErrorV (HRESULT aResultCode, const char *aText,
1779 va_list aArgs)
1780 {
1781 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError
1782 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText, aArgs, true /* aLogIt */);
1783 return rc;
1784 }
1785
1786 /**
1787 * This method is the same as #setErrorV() except that it makes sure @a
1788 * aResultCode doesn't have the error severity bit (31) set when passed
1789 * down to the created IVirtualBoxErrorInfo object.
1790 *
1791 * The error severity bit is always cleared by this call, thereof you can
1792 * use ordinary E_XXX result code constants, for convenience. However, this
1793 * behavior may be non-standard on some COM platforms.
1794 */
1795 static HRESULT setWarningV (HRESULT aResultCode, const char *aText,
1796 va_list aArgs)
1797 {
1798 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setWarning
1799 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText, aArgs);
1800 return rc;
1801 }
1802
1803 /**
1804 * Sets the error information for the current thread, BStr variant.
1805 * A convenience method that automatically sets the default interface
1806 * ID (taken from the I template argument) and the component name
1807 * (a value of C::getComponentName()).
1808 *
1809 * This method is preferred if you have a ready (translated and formatted)
1810 * Bstr string, because it omits an extra conversion Utf8Str -> Bstr.
1811 *
1812 * See #setError (HRESULT, const GUID &, const wchar_t *, const char *text, ...)
1813 * and #setError (HRESULT, const char *, ...) for details.
1814 */
1815 static HRESULT setErrorBstr (HRESULT aResultCode, const Bstr &aText)
1816 {
1817 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError
1818 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText, true /* aLogIt */);
1819 return rc;
1820 }
1821
1822 /**
1823 * This method is the same as #setErrorBstr() except that it makes sure @a
1824 * aResultCode doesn't have the error severity bit (31) set when passed
1825 * down to the created IVirtualBoxErrorInfo object.
1826 *
1827 * The error severity bit is always cleared by this call, thereof you can
1828 * use ordinary E_XXX result code constants, for convenience. However, this
1829 * behavior may be non-standard on some COM platforms.
1830 */
1831 static HRESULT setWarningBstr (HRESULT aResultCode, const Bstr &aText)
1832 {
1833 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setWarning
1834 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText);
1835 return rc;
1836 }
1837
1838 /**
1839 * Sets the error information for the current thread.
1840 * A convenience method that automatically sets the component name
1841 * (a value of C::getComponentName()), but allows to specify the interface
1842 * id manually.
1843 *
1844 * See #setError (HRESULT, const GUID &, const wchar_t *, const char *text, ...)
1845 * for details.
1846 */
1847 static HRESULT setError (HRESULT aResultCode, const GUID &aIID,
1848 const char *aText, ...)
1849 {
1850 va_list args;
1851 va_start (args, aText);
1852 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError
1853 (aResultCode, aIID, C::getComponentName(), aText, args, true /* aLogIt */);
1854 va_end (args);
1855 return rc;
1856 }
1857
1858 /**
1859 * This method is the same as #setError() except that it makes sure @a
1860 * aResultCode doesn't have the error severity bit (31) set when passed
1861 * down to the created IVirtualBoxErrorInfo object.
1862 *
1863 * The error severity bit is always cleared by this call, thereof you can
1864 * use ordinary E_XXX result code constants, for convenience. However, this
1865 * behavior may be non-standard on some COM platforms.
1866 */
1867 static HRESULT setWarning (HRESULT aResultCode, const GUID &aIID,
1868 const char *aText, ...)
1869 {
1870 va_list args;
1871 va_start (args, aText);
1872 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setWarning
1873 (aResultCode, aIID, C::getComponentName(), aText, args);
1874 va_end (args);
1875 return rc;
1876 }
1877
1878 /**
1879 * Sets the error information for the current thread but doesn't put
1880 * anything in the release log. This is very useful for avoiding
1881 * harmless error from causing confusion.
1882 *
1883 * It is otherwise identical to #setError (HRESULT, const char *text, ...).
1884 */
1885 static HRESULT setErrorNoLog (HRESULT aResultCode, const char *aText, ...)
1886 {
1887 va_list args;
1888 va_start (args, aText);
1889 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError
1890 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText, args, false /* aLogIt */);
1891 va_end (args);
1892 return rc;
1893 }
1894
1895private:
1896
1897};
1898
1899////////////////////////////////////////////////////////////////////////////////
1900
1901/**
1902 * Base class to track VirtualBoxBase children of the component.
1903 *
1904 * This class is a preferable VirtualBoxBase replacement for components
1905 * that operate with collections of child components. It gives two useful
1906 * possibilities:
1907 *
1908 * <ol><li>
1909 * Given an IUnknown instance, it's possible to quickly determine
1910 * whether this instance represents a child object created by the given
1911 * component, and if so, get a valid VirtualBoxBase pointer to the child
1912 * object. The returned pointer can be then safely casted to the
1913 * actual class of the child object (to get access to its "internal"
1914 * non-interface methods) provided that no other child components implement
1915 * the same initial interface IUnknown is queried from.
1916 * </li><li>
1917 * When the parent object uninitializes itself, it can easily unintialize
1918 * all its VirtualBoxBase derived children (using their
1919 * VirtualBoxBase::uninit() implementations). This is done simply by
1920 * calling the #uninitDependentChildren() method.
1921 * </li></ol>
1922 *
1923 * In order to let the above work, the following must be done:
1924 * <ol><li>
1925 * When a child object is initialized, it calls #addDependentChild() of
1926 * its parent to register itself within the list of dependent children.
1927 * </li><li>
1928 * When a child object it is uninitialized, it calls #removeDependentChild()
1929 * to unregister itself. This must be done <b>after</b> the child has called
1930 * setReady(false) to indicate it is no more valid, and <b>not</b> from under
1931 * the child object's lock. Note also, that the first action the child's
1932 * uninit() implementation must do is to check for readiness after acquiring
1933 * the object's lock and return immediately if not ready.
1934 * </li></ol>
1935 *
1936 * Children added by #addDependentChild() are <b>weakly</b> referenced
1937 * (i.e. AddRef() is not called), so when a child is externally destructed
1938 * (i.e. its reference count goes to zero), it will automatically remove
1939 * itself from a map of dependent children, provided that it follows the
1940 * rules described here.
1941 *
1942 * @note
1943 * Because of weak referencing, deadlocks and assertions are very likely
1944 * if #addDependentChild() or #removeDependentChild() are used incorrectly
1945 * (called at inappropriate times). Check the above rules once more.
1946 *
1947 * @deprecated Use VirtualBoxBaseWithChildrenNEXT for new classes.
1948 */
1949class VirtualBoxBaseWithChildren : public VirtualBoxBase
1950{
1951public:
1952
1953 VirtualBoxBaseWithChildren()
1954 : mUninitDoneSem (NIL_RTSEMEVENT), mChildrenLeft (0)
1955 {}
1956
1957 virtual ~VirtualBoxBaseWithChildren()
1958 {}
1959
1960 /**
1961 * Adds the given child to the map of dependent children.
1962 * Intended to be called from the child's init() method,
1963 * from under the child's lock.
1964 *
1965 * @param C the child object to add (must inherit VirtualBoxBase AND
1966 * implement some interface)
1967 */
1968 template <class C>
1969 void addDependentChild (C *child)
1970 {
1971 AssertReturn (child, (void) 0);
1972 addDependentChild (child, child);
1973 }
1974
1975 /**
1976 * Removes the given child from the map of dependent children.
1977 * Must be called <b>after<b> the child has called setReady(false), and
1978 * <b>not</b> from under the child object's lock.
1979 *
1980 * @param C the child object to remove (must inherit VirtualBoxBase AND
1981 * implement some interface)
1982 */
1983 template <class C>
1984 void removeDependentChild (C *child)
1985 {
1986 AssertReturn (child, (void) 0);
1987 /// @todo (r=dmik) the below check (and the relevant comment above)
1988 // seems to be not necessary any more once we completely switch to
1989 // the NEXT locking scheme. This requires altering removeDependentChild()
1990 // and uninitDependentChildren() as well (due to the new state scheme,
1991 // there is a separate mutex for state transition, so calling the
1992 // child's uninit() from under the children map lock should not produce
1993 // dead-locks any more).
1994 Assert (!child->isWriteLockOnCurrentThread() || child->lockHandle() == lockHandle());
1995 removeDependentChild (ComPtr <IUnknown> (child));
1996 }
1997
1998protected:
1999
2000 void uninitDependentChildren();
2001
2002 VirtualBoxBase *getDependentChild (const ComPtr <IUnknown> &unk);
2003
2004private:
2005
2006 void addDependentChild (const ComPtr <IUnknown> &unk, VirtualBoxBase *child);
2007 void removeDependentChild (const ComPtr <IUnknown> &unk);
2008
2009 typedef std::map <IUnknown *, VirtualBoxBase *> DependentChildren;
2010 DependentChildren mDependentChildren;
2011
2012 WriteLockHandle mMapLock;
2013
2014 RTSEMEVENT mUninitDoneSem;
2015 unsigned mChildrenLeft;
2016};
2017
2018////////////////////////////////////////////////////////////////////////////////
2019
2020/**
2021 * Base class to track VirtualBoxBaseNEXT chlidren of the component.
2022 *
2023 * This class is a preferrable VirtualBoxBase replacement for components that
2024 * operate with collections of child components. It gives two useful
2025 * possibilities:
2026 *
2027 * <ol><li>
2028 * Given an IUnknown instance, it's possible to quickly determine
2029 * whether this instance represents a child object that belongs to the
2030 * given component, and if so, get a valid VirtualBoxBase pointer to the
2031 * child object. The returned pointer can be then safely casted to the
2032 * actual class of the child object (to get access to its "internal"
2033 * non-interface methods) provided that no other child components implement
2034 * the same original COM interface IUnknown is queried from.
2035 * </li><li>
2036 * When the parent object uninitializes itself, it can easily unintialize
2037 * all its VirtualBoxBase derived children (using their
2038 * VirtualBoxBase::uninit() implementations). This is done simply by
2039 * calling the #uninitDependentChildren() method.
2040 * </li></ol>
2041 *
2042 * In order to let the above work, the following must be done:
2043 * <ol><li>
2044 * When a child object is initialized, it calls #addDependentChild() of
2045 * its parent to register itself within the list of dependent children.
2046 * </li><li>
2047 * When the child object it is uninitialized, it calls
2048 * #removeDependentChild() to unregister itself.
2049 * </li></ol>
2050 *
2051 * Note that if the parent object does not call #uninitDependentChildren() when
2052 * it gets uninitialized, it must call uninit() methods of individual children
2053 * manually to disconnect them; a failure to do so will cause crashes in these
2054 * methods when children get destroyed. The same applies to children not calling
2055 * #removeDependentChild() when getting destroyed.
2056 *
2057 * Note that children added by #addDependentChild() are <b>weakly</b> referenced
2058 * (i.e. AddRef() is not called), so when a child object is deleted externally
2059 * (because it's reference count goes to zero), it will automatically remove
2060 * itself from the map of dependent children provided that it follows the rules
2061 * described here.
2062 *
2063 * Access to the child list is serialized using the #childrenLock() lock handle
2064 * (which defaults to the general object lock handle (see
2065 * VirtualBoxBase::lockHandle()). This lock is used by all add/remove methods of
2066 * this class so be aware of the need to preserve the {parent, child} lock order
2067 * when calling these methods.
2068 *
2069 * Read individual method descriptions to get further information.
2070 *
2071 * @todo This is a VirtualBoxBaseWithChildren equivalent that uses the
2072 * VirtualBoxBaseNEXT implementation. Will completely supersede
2073 * VirtualBoxBaseWithChildren after the old VirtualBoxBase implementation
2074 * has gone.
2075 */
2076class VirtualBoxBaseWithChildrenNEXT : public VirtualBoxBaseNEXT
2077{
2078public:
2079
2080 VirtualBoxBaseWithChildrenNEXT()
2081 {}
2082
2083 virtual ~VirtualBoxBaseWithChildrenNEXT()
2084 {}
2085
2086 /**
2087 * Lock handle to use when adding/removing child objects from the list of
2088 * children. It is guaranteed that no any other lock is requested in methods
2089 * of this class while holding this lock.
2090 *
2091 * @warning By default, this simply returns the general object's lock handle
2092 * (see VirtualBoxBase::lockHandle()) which is sufficient for most
2093 * cases.
2094 */
2095 virtual RWLockHandle *childrenLock() { return lockHandle(); }
2096
2097 /**
2098 * Adds the given child to the list of dependent children.
2099 *
2100 * Usually gets called from the child's init() method.
2101 *
2102 * @note @a aChild (unless it is in InInit state) must be protected by
2103 * VirtualBoxBase::AutoCaller to make sure it is not uninitialized on
2104 * another thread during this method's call.
2105 *
2106 * @note When #childrenLock() is not overloaded (returns the general object
2107 * lock) and this method is called from under the child's read or
2108 * write lock, make sure the {parent, child} locking order is
2109 * preserved by locking the callee (this object) for writing before
2110 * the child's lock.
2111 *
2112 * @param aChild Child object to add (must inherit VirtualBoxBase AND
2113 * implement some interface).
2114 *
2115 * @note Locks #childrenLock() for writing.
2116 */
2117 template <class C>
2118 void addDependentChild (C *aChild)
2119 {
2120 AssertReturnVoid (aChild != NULL);
2121 doAddDependentChild (ComPtr <IUnknown> (aChild), aChild);
2122 }
2123
2124 /**
2125 * Equivalent to template <class C> void addDependentChild (C *aChild)
2126 * but takes a ComObjPtr <C> argument.
2127 */
2128 template <class C>
2129 void addDependentChild (const ComObjPtr <C> &aChild)
2130 {
2131 AssertReturnVoid (!aChild.isNull());
2132 doAddDependentChild (ComPtr <IUnknown> (static_cast <C *> (aChild)), aChild);
2133 }
2134
2135 /**
2136 * Removes the given child from the list of dependent children.
2137 *
2138 * Usually gets called from the child's uninit() method.
2139 *
2140 * Keep in mind that the called (parent) object may be no longer available
2141 * (i.e. may be deleted deleted) after this method returns, so you must not
2142 * call any other parent's methods after that!
2143 *
2144 * @note Locks #childrenLock() for writing.
2145 *
2146 * @note @a aChild (unless it is in InUninit state) must be protected by
2147 * VirtualBoxBase::AutoCaller to make sure it is not uninitialized on
2148 * another thread during this method's call.
2149 *
2150 * @note When #childrenLock() is not overloaded (returns the general object
2151 * lock) and this method is called from under the child's read or
2152 * write lock, make sure the {parent, child} locking order is
2153 * preserved by locking the callee (this object) for writing before
2154 * the child's lock. This is irrelevant when the method is called from
2155 * under this object's VirtualBoxBaseProto::AutoUninitSpan (i.e. in
2156 * InUninit state) since in this case no locking is done.
2157 *
2158 * @param aChild Child object to remove.
2159 *
2160 * @note Locks #childrenLock() for writing.
2161 */
2162 template <class C>
2163 void removeDependentChild (C *aChild)
2164 {
2165 AssertReturnVoid (aChild != NULL);
2166 doRemoveDependentChild (ComPtr <IUnknown> (aChild));
2167 }
2168
2169 /**
2170 * Equivalent to template <class C> void removeDependentChild (C *aChild)
2171 * but takes a ComObjPtr <C> argument.
2172 */
2173 template <class C>
2174 void removeDependentChild (const ComObjPtr <C> &aChild)
2175 {
2176 AssertReturnVoid (!aChild.isNull());
2177 doRemoveDependentChild (ComPtr <IUnknown> (static_cast <C *> (aChild)));
2178 }
2179
2180protected:
2181
2182 void uninitDependentChildren();
2183
2184 VirtualBoxBaseNEXT *getDependentChild (const ComPtr <IUnknown> &aUnk);
2185
2186private:
2187
2188 /// @todo temporarily reinterpret VirtualBoxBase * as VirtualBoxBaseNEXT *
2189 // until ported HardDisk and Progress to the new scheme.
2190 void doAddDependentChild (IUnknown *aUnk, VirtualBoxBase *aChild)
2191 {
2192 doAddDependentChild (aUnk,
2193 reinterpret_cast <VirtualBoxBaseNEXT *> (aChild));
2194 }
2195
2196 void doAddDependentChild (IUnknown *aUnk, VirtualBoxBaseNEXT *aChild);
2197 void doRemoveDependentChild (IUnknown *aUnk);
2198
2199 typedef std::map <IUnknown *, VirtualBoxBaseNEXT *> DependentChildren;
2200 DependentChildren mDependentChildren;
2201};
2202
2203////////////////////////////////////////////////////////////////////////////////
2204
2205/**
2206 * Base class to track component's children of some particular type.
2207 *
2208 * This class is similar to VirtualBoxBaseWithChildren, with the exception
2209 * that all children must be of the same type. For this reason, it's not
2210 * necessary to use a map to store children, so a list is used instead.
2211 *
2212 * As opposed to VirtualBoxBaseWithChildren, children added by
2213 * #addDependentChild() are <b>strongly</b> referenced, so that they cannot
2214 * be externally destructed until #removeDependentChild() is called.
2215 *
2216 * Also, this class doesn't have the
2217 * VirtualBoxBaseWithChildrenNEXT::getDependentChild() method because it would
2218 * be not fast for long lists.
2219 *
2220 * @param C type of child objects (must inherit VirtualBoxBase AND
2221 * implement some interface)
2222 *
2223 * @deprecated Use VirtualBoxBaseWithTypedChildrenNEXT for new classes.
2224 */
2225template <class C>
2226class VirtualBoxBaseWithTypedChildren : public VirtualBoxBase
2227{
2228public:
2229
2230 typedef std::list <ComObjPtr <C> > DependentChildren;
2231
2232 VirtualBoxBaseWithTypedChildren() : mInUninit (false) {}
2233
2234 virtual ~VirtualBoxBaseWithTypedChildren() {}
2235
2236 /**
2237 * Adds the given child to the list of dependent children.
2238 * Must be called from the child's init() method,
2239 * from under the child's lock.
2240 *
2241 * @param C the child object to add (must inherit VirtualBoxBase AND
2242 * implement some interface)
2243 */
2244 void addDependentChild (C *child)
2245 {
2246 AssertReturn (child, (void) 0);
2247
2248 AutoWriteLock alock (mMapLock);
2249 if (mInUninit)
2250 return;
2251
2252 mDependentChildren.push_back (child);
2253 }
2254
2255 /**
2256 * Removes the given child from the list of dependent children.
2257 * Must be called from the child's uninit() method,
2258 * under the child's lock.
2259 *
2260 * @param C the child object to remove (must inherit VirtualBoxBase AND
2261 * implement some interface)
2262 */
2263 void removeDependentChild (C *child)
2264 {
2265 AssertReturn (child, (void) 0);
2266
2267 AutoWriteLock alock (mMapLock);
2268 if (mInUninit)
2269 return;
2270
2271 mDependentChildren.remove (child);
2272 }
2273
2274protected:
2275
2276 /**
2277 * Returns an internal lock handle to lock the list of children
2278 * returned by #dependentChildren() using AutoReadLock/AutoWriteLock:
2279 * <code>
2280 * AutoReadLock alock (dependentChildrenLock());
2281 * </code>
2282 *
2283 * This is necessary for example to access the list of children returned by
2284 * #dependentChildren().
2285 */
2286 RWLockHandle *dependentChildrenLock() const { return &mMapLock; }
2287
2288 /**
2289 * Returns the read-only list of all dependent children.
2290 * @note
2291 * Access the returned list (iterate, get size etc.) only after
2292 * doing |AutoWriteLock alock (dependentChildrenLock());|!
2293 */
2294 const DependentChildren &dependentChildren() const { return mDependentChildren; }
2295
2296 /**
2297 * Uninitializes all dependent children registered with #addDependentChild().
2298 *
2299 * @note
2300 * This method will call uninit() methods of children. If these methods
2301 * access the parent object, uninitDependentChildren() must be called
2302 * either at the beginning of the parent uninitialization sequence (when
2303 * it is still operational) or after setReady(false) is called to
2304 * indicate the parent is out of action.
2305 */
2306 void uninitDependentChildren()
2307 {
2308 AutoWriteLock alock (this);
2309 AutoWriteLock mapLock (mMapLock);
2310
2311 if (mDependentChildren.size())
2312 {
2313 // set flag to ignore #removeDependentChild() called from child->uninit()
2314 mInUninit = true;
2315
2316 // leave the locks to let children waiting for #removeDependentChild() run
2317 mapLock.leave();
2318 alock.leave();
2319
2320 for (typename DependentChildren::iterator it = mDependentChildren.begin();
2321 it != mDependentChildren.end(); ++ it)
2322 {
2323 C *child = (*it);
2324 Assert (child);
2325 if (child)
2326 child->uninit();
2327 }
2328 mDependentChildren.clear();
2329
2330 alock.enter();
2331 mapLock.enter();
2332
2333 mInUninit = false;
2334 }
2335 }
2336
2337 /**
2338 * Removes (detaches) all dependent children registered with
2339 * #addDependentChild(), without uninitializing them.
2340 *
2341 * @note This method must be called from under the main object's lock
2342 */
2343 void removeDependentChildren()
2344 {
2345 AutoWriteLock alock (mMapLock);
2346 mDependentChildren.clear();
2347 }
2348
2349private:
2350
2351 DependentChildren mDependentChildren;
2352
2353 bool mInUninit;
2354 mutable RWLockHandle mMapLock;
2355};
2356
2357////////////////////////////////////////////////////////////////////////////////
2358
2359/**
2360 * Base class to track component's children of the particular type.
2361 *
2362 * This class is similar to VirtualBoxBaseWithChildrenNEXT with the exception
2363 * that all children must be of the same type. For this reason, it's not
2364 * necessary to use a map to store children -- a list is used instead.
2365 *
2366 * Also, as opposed to VirtualBoxBaseWithChildren, children added by
2367 * #addDependentChild() are <b>strongly</b> referenced, so that they cannot be
2368 * deleted (even by a third party) until #removeDependentChild() is called on
2369 * them. This also means that a failure to call #removeDependentChild() and
2370 * #uninitDependentChildren() at appropriate times as described in
2371 * VirtualBoxBaseWithChildrenNEXT may cause stuck references that won't be able
2372 * uninitialize themselves.
2373 *
2374 * See individual method descriptions for further information.
2375 *
2376 * @param C Type of child objects (must inherit VirtualBoxBase AND implement
2377 * some interface).
2378 *
2379 * @todo This is a VirtualBoxBaseWithChildren equivalent that uses the
2380 * VirtualBoxBaseNEXT implementation. Will completely supersede
2381 * VirtualBoxBaseWithChildren after the old VirtualBoxBase implementation
2382 * has gone.
2383 */
2384template <class C>
2385class VirtualBoxBaseWithTypedChildrenNEXT : public VirtualBoxBaseNEXT
2386{
2387public:
2388
2389 typedef std::list <ComObjPtr <C> > DependentChildren;
2390
2391 VirtualBoxBaseWithTypedChildrenNEXT() {}
2392
2393 virtual ~VirtualBoxBaseWithTypedChildrenNEXT() {}
2394
2395 /**
2396 * Lock handle to use when adding/removing child objects from the list of
2397 * children. It is guaranteed that no any other lock is requested in methods
2398 * of this class while holding this lock.
2399 *
2400 * @warning By default, this simply returns the general object's lock handle
2401 * (see VirtualBoxBase::lockHandle()) which is sufficient for most
2402 * cases.
2403 */
2404 virtual RWLockHandle *childrenLock() { return lockHandle(); }
2405
2406 /**
2407 * Adds the given child to the list of dependent children.
2408 *
2409 * Usually gets called from the child's init() method.
2410 *
2411 * @note @a aChild (unless it is in InInit state) must be protected by
2412 * VirtualBoxBase::AutoCaller to make sure it is not uninitialized on
2413 * another thread during this method's call.
2414 *
2415 * @note When #childrenLock() is not overloaded (returns the general object
2416 * lock) and this method is called from under the child's read or
2417 * write lock, make sure the {parent, child} locking order is
2418 * preserved by locking the callee (this object) for writing before
2419 * the child's lock.
2420 *
2421 * @param aChild Child object to add.
2422 *
2423 * @note Locks #childrenLock() for writing.
2424 */
2425 void addDependentChild (C *aChild)
2426 {
2427 AssertReturnVoid (aChild != NULL);
2428
2429 AutoCaller autoCaller (this);
2430
2431 /* sanity */
2432 AssertReturnVoid (autoCaller.state() == InInit ||
2433 autoCaller.state() == Ready ||
2434 autoCaller.state() == Limited);
2435
2436 AutoWriteLock chLock (childrenLock());
2437 mDependentChildren.push_back (aChild);
2438 }
2439
2440 /**
2441 * Removes the given child from the list of dependent children.
2442 *
2443 * Usually gets called from the child's uninit() method.
2444 *
2445 * Keep in mind that the called (parent) object may be no longer available
2446 * (i.e. may be deleted deleted) after this method returns, so you must not
2447 * call any other parent's methods after that!
2448 *
2449 * @note @a aChild (unless it is in InUninit state) must be protected by
2450 * VirtualBoxBase::AutoCaller to make sure it is not uninitialized on
2451 * another thread during this method's call.
2452 *
2453 * @note When #childrenLock() is not overloaded (returns the general object
2454 * lock) and this method is called from under the child's read or
2455 * write lock, make sure the {parent, child} locking order is
2456 * preserved by locking the callee (this object) for writing before
2457 * the child's lock. This is irrelevant when the method is called from
2458 * under this object's AutoUninitSpan (i.e. in InUninit state) since
2459 * in this case no locking is done.
2460 *
2461 * @param aChild Child object to remove.
2462 *
2463 * @note Locks #childrenLock() for writing.
2464 */
2465 void removeDependentChild (C *aChild)
2466 {
2467 AssertReturnVoid (aChild);
2468
2469 AutoCaller autoCaller (this);
2470
2471 /* sanity */
2472 AssertReturnVoid (autoCaller.state() == InUninit ||
2473 autoCaller.state() == InInit ||
2474 autoCaller.state() == Ready ||
2475 autoCaller.state() == Limited);
2476
2477 /* return shortly; we are strongly referenced so the object won't get
2478 * deleted if it calls init() before uninitDependentChildren() does
2479 * and therefore the list will still contain a valid reference that will
2480 * be correctly processed by uninitDependentChildren() anyway */
2481 if (autoCaller.state() == InUninit)
2482 return;
2483
2484 AutoWriteLock chLock (childrenLock());
2485 mDependentChildren.remove (aChild);
2486 }
2487
2488protected:
2489
2490 /**
2491 * Returns the read-only list of all dependent children.
2492 *
2493 * @note Access the returned list (iterate, get size etc.) only after making
2494 * sure #childrenLock() is locked for reading or for writing!
2495 */
2496 const DependentChildren &dependentChildren() const { return mDependentChildren; }
2497
2498 /**
2499 * Uninitializes all dependent children registered on this object with
2500 * #addDependentChild().
2501 *
2502 * Must be called from within the VirtualBoxBaseProto::AutoUninitSpan (i.e.
2503 * typically from this object's uninit() method) to uninitialize children
2504 * before this object goes out of service and becomes unusable.
2505 *
2506 * Note that this method will call uninit() methods of child objects. If
2507 * these methods need to call the parent object during uninitialization,
2508 * #uninitDependentChildren() must be called before the relevant part of the
2509 * parent is uninitialized: usually at the beginning of the parent
2510 * uninitialization sequence.
2511 *
2512 * @note May lock something through the called children.
2513 */
2514 void uninitDependentChildren()
2515 {
2516 AutoCaller autoCaller (this);
2517
2518 /* We don't want to hold the childrenLock() write lock here (necessary
2519 * to protect mDependentChildren) when uninitializing children because
2520 * we want to avoid a possible deadlock where we could get stuck in
2521 * child->uninit() blocked by AutoUninitSpan waiting for the number of
2522 * child's callers to drop to zero (or for another AutoUninitSpan to
2523 * finish), while some other thread is stuck in our
2524 * removeDependentChild() method called for that child and waiting for
2525 * the childrenLock()'s write lock.
2526 *
2527 * The only safe place to not lock and keep accessing our data members
2528 * is the InUninit state (no active call to our object may exist on
2529 * another thread when we are in InUinint, provided that all such calls
2530 * use the AutoCaller class of course). InUinint is also used as a flag
2531 * by removeDependentChild() that prevents touching mDependentChildren
2532 * from outside. Therefore, we assert. Note that InInit is also fine
2533 * since no any object may access us by that time.
2534 */
2535 AssertReturnVoid (autoCaller.state() == InUninit ||
2536 autoCaller.state() == InInit);
2537
2538 if (mDependentChildren.size())
2539 {
2540 for (typename DependentChildren::iterator it = mDependentChildren.begin();
2541 it != mDependentChildren.end(); ++ it)
2542 {
2543 C *child = (*it);
2544 Assert (child);
2545
2546 /* Note that if child->uninit() happens to be called on another
2547 * thread right before us and is not yet finished, the second
2548 * uninit() call will wait until the first one has done so
2549 * (thanks to AutoUninitSpan). */
2550 if (child)
2551 child->uninit();
2552 }
2553
2554 /* release all strong references we hold */
2555 mDependentChildren.clear();
2556 }
2557 }
2558
2559 /**
2560 * Removes (detaches) all dependent children registered with
2561 * #addDependentChild(), without uninitializing them.
2562 *
2563 * @note @a |this| (unless it is in InUninit state) must be protected by
2564 * VirtualBoxBase::AutoCaller to make sure it is not uninitialized on
2565 * another thread during this method's call.
2566 *
2567 * @note Locks #childrenLock() for writing.
2568 */
2569 void removeDependentChildren()
2570 {
2571 AutoWriteLock chLock (childrenLock());
2572 mDependentChildren.clear();
2573 }
2574
2575private:
2576
2577 DependentChildren mDependentChildren;
2578};
2579
2580////////////////////////////////////////////////////////////////////////////////
2581
2582/// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
2583/**
2584 * Simple template that manages data structure allocation/deallocation
2585 * and supports data pointer sharing (the instance that shares the pointer is
2586 * not responsible for memory deallocation as opposed to the instance that
2587 * owns it).
2588 */
2589template <class D>
2590class Shareable
2591{
2592public:
2593
2594 Shareable() : mData (NULL), mIsShared (FALSE) {}
2595 ~Shareable() { free(); }
2596
2597 void allocate() { attach (new D); }
2598
2599 virtual void free() {
2600 if (mData) {
2601 if (!mIsShared)
2602 delete mData;
2603 mData = NULL;
2604 mIsShared = false;
2605 }
2606 }
2607
2608 void attach (D *data) {
2609 AssertMsg (data, ("new data must not be NULL"));
2610 if (data && mData != data) {
2611 if (mData && !mIsShared)
2612 delete mData;
2613 mData = data;
2614 mIsShared = false;
2615 }
2616 }
2617
2618 void attach (Shareable &data) {
2619 AssertMsg (
2620 data.mData == mData || !data.mIsShared,
2621 ("new data must not be shared")
2622 );
2623 if (this != &data && !data.mIsShared) {
2624 attach (data.mData);
2625 data.mIsShared = true;
2626 }
2627 }
2628
2629 void share (D *data) {
2630 AssertMsg (data, ("new data must not be NULL"));
2631 if (mData != data) {
2632 if (mData && !mIsShared)
2633 delete mData;
2634 mData = data;
2635 mIsShared = true;
2636 }
2637 }
2638
2639 void share (const Shareable &data) { share (data.mData); }
2640
2641 void attachCopy (const D *data) {
2642 AssertMsg (data, ("data to copy must not be NULL"));
2643 if (data)
2644 attach (new D (*data));
2645 }
2646
2647 void attachCopy (const Shareable &data) {
2648 attachCopy (data.mData);
2649 }
2650
2651 virtual D *detach() {
2652 D *d = mData;
2653 mData = NULL;
2654 mIsShared = false;
2655 return d;
2656 }
2657
2658 D *data() const {
2659 return mData;
2660 }
2661
2662 D *operator->() const {
2663 AssertMsg (mData, ("data must not be NULL"));
2664 return mData;
2665 }
2666
2667 bool isNull() const { return mData == NULL; }
2668 bool operator!() const { return isNull(); }
2669
2670 bool isShared() const { return mIsShared; }
2671
2672protected:
2673
2674 D *mData;
2675 bool mIsShared;
2676};
2677
2678/// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
2679/**
2680 * Simple template that enhances Shareable<> and supports data
2681 * backup/rollback/commit (using the copy constructor of the managed data
2682 * structure).
2683 */
2684template <class D>
2685class Backupable : public Shareable <D>
2686{
2687public:
2688
2689 Backupable() : Shareable <D> (), mBackupData (NULL) {}
2690
2691 void free()
2692 {
2693 AssertMsg (this->mData || !mBackupData, ("backup must be NULL if data is NULL"));
2694 rollback();
2695 Shareable <D>::free();
2696 }
2697
2698 D *detach()
2699 {
2700 AssertMsg (this->mData || !mBackupData, ("backup must be NULL if data is NULL"));
2701 rollback();
2702 return Shareable <D>::detach();
2703 }
2704
2705 void share (const Backupable &data)
2706 {
2707 AssertMsg (!data.isBackedUp(), ("data to share must not be backed up"));
2708 if (!data.isBackedUp())
2709 Shareable <D>::share (data.mData);
2710 }
2711
2712 /**
2713 * Stores the current data pointer in the backup area, allocates new data
2714 * using the copy constructor on current data and makes new data active.
2715 */
2716 void backup()
2717 {
2718 AssertMsg (this->mData, ("data must not be NULL"));
2719 if (this->mData && !mBackupData)
2720 {
2721 mBackupData = this->mData;
2722 this->mData = new D (*mBackupData);
2723 }
2724 }
2725
2726 /**
2727 * Deletes new data created by #backup() and restores previous data pointer
2728 * stored in the backup area, making it active again.
2729 */
2730 void rollback()
2731 {
2732 if (this->mData && mBackupData)
2733 {
2734 delete this->mData;
2735 this->mData = mBackupData;
2736 mBackupData = NULL;
2737 }
2738 }
2739
2740 /**
2741 * Commits current changes by deleting backed up data and clearing up the
2742 * backup area. The new data pointer created by #backup() remains active
2743 * and becomes the only managed pointer.
2744 *
2745 * This method is much faster than #commitCopy() (just a single pointer
2746 * assignment operation), but makes the previous data pointer invalid
2747 * (because it is freed). For this reason, this method must not be
2748 * used if it's possible that data managed by this instance is shared with
2749 * some other Shareable instance. See #commitCopy().
2750 */
2751 void commit()
2752 {
2753 if (this->mData && mBackupData)
2754 {
2755 if (!this->mIsShared)
2756 delete mBackupData;
2757 mBackupData = NULL;
2758 this->mIsShared = false;
2759 }
2760 }
2761
2762 /**
2763 * Commits current changes by assigning new data to the previous data
2764 * pointer stored in the backup area using the assignment operator.
2765 * New data is deleted, the backup area is cleared and the previous data
2766 * pointer becomes active and the only managed pointer.
2767 *
2768 * This method is slower than #commit(), but it keeps the previous data
2769 * pointer valid (i.e. new data is copied to the same memory location).
2770 * For that reason it's safe to use this method on instances that share
2771 * managed data with other Shareable instances.
2772 */
2773 void commitCopy()
2774 {
2775 if (this->mData && mBackupData)
2776 {
2777 *mBackupData = *(this->mData);
2778 delete this->mData;
2779 this->mData = mBackupData;
2780 mBackupData = NULL;
2781 }
2782 }
2783
2784 void assignCopy (const D *data)
2785 {
2786 AssertMsg (this->mData, ("data must not be NULL"));
2787 AssertMsg (data, ("data to copy must not be NULL"));
2788 if (this->mData && data)
2789 {
2790 if (!mBackupData)
2791 {
2792 mBackupData = this->mData;
2793 this->mData = new D (*data);
2794 }
2795 else
2796 *this->mData = *data;
2797 }
2798 }
2799
2800 void assignCopy (const Backupable &data)
2801 {
2802 assignCopy (data.mData);
2803 }
2804
2805 bool isBackedUp() const
2806 {
2807 return mBackupData != NULL;
2808 }
2809
2810 bool hasActualChanges() const
2811 {
2812 AssertMsg (this->mData, ("data must not be NULL"));
2813 return this->mData != NULL && mBackupData != NULL &&
2814 !(*this->mData == *mBackupData);
2815 }
2816
2817 D *backedUpData() const
2818 {
2819 return mBackupData;
2820 }
2821
2822protected:
2823
2824 D *mBackupData;
2825};
2826
2827#if defined VBOX_MAIN_SETTINGS_ADDONS
2828
2829/**
2830 * Settings API additions.
2831 */
2832namespace settings
2833{
2834
2835/// @todo once string data in Bstr and Utf8Str is auto_ref_ptr, enable the
2836/// code below
2837
2838#if 0
2839
2840/** Specialization of FromString for Bstr. */
2841template<> com::Bstr FromString <com::Bstr> (const char *aValue);
2842
2843#endif
2844
2845/** Specialization of ToString for Bstr. */
2846template<> stdx::char_auto_ptr
2847ToString <com::Bstr> (const com::Bstr &aValue, unsigned int aExtra);
2848
2849/** Specialization of FromString for Guid. */
2850template<> com::Guid FromString <com::Guid> (const char *aValue);
2851
2852/** Specialization of ToString for Guid. */
2853template<> stdx::char_auto_ptr
2854ToString <com::Guid> (const com::Guid &aValue, unsigned int aExtra);
2855
2856} /* namespace settings */
2857
2858#endif /* VBOX_MAIN_SETTINGS_ADDONS */
2859
2860#endif // ____H_VIRTUALBOXBASEIMPL
2861/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use