VirtualBox

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

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

Main: Added a bunch of CheckComArg macros.

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

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