VirtualBox

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

Last change on this file since 14949 was 14949, checked in by vboxsync, 16 years ago

Appended vim modeline to set tabstop and expand tabs (in the way
suggested by our coding guidelines).

  • 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)\n", (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.

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