VirtualBox

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

Last change on this file since 8971 was 8744, checked in by vboxsync, 17 years ago

Moved the filter running over to USBProxyService (from Host). Split up the USBProxyService construction using an init() method like the rest of the classes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 84.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.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#ifndef ____H_VIRTUALBOXBASEIMPL
23#define ____H_VIRTUALBOXBASEIMPL
24
25#include "VBox/com/string.h"
26#include "VBox/com/Guid.h"
27#include "VBox/com/ptr.h"
28#include "VBox/com/ErrorInfo.h"
29
30#include "VBox/com/VirtualBox.h"
31
32#include <VBox/settings.h>
33
34#include "AutoLock.h"
35
36using namespace com;
37using namespace util;
38
39#include <iprt/cdefs.h>
40#include <iprt/critsect.h>
41#include <iprt/thread.h>
42
43#include <list>
44#include <map>
45
46#if !defined (VBOX_WITH_XPCOM)
47
48#include <atlcom.h>
49
50// use a special version of the singleton class factory,
51// see KB811591 in msdn for more info.
52
53#undef DECLARE_CLASSFACTORY_SINGLETON
54#define DECLARE_CLASSFACTORY_SINGLETON(obj) DECLARE_CLASSFACTORY_EX(CMyComClassFactorySingleton<obj>)
55
56template <class T>
57class CMyComClassFactorySingleton : public CComClassFactory
58{
59public:
60 CMyComClassFactorySingleton() : m_hrCreate(S_OK){}
61 virtual ~CMyComClassFactorySingleton(){}
62 // IClassFactory
63 STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj)
64 {
65 HRESULT hRes = E_POINTER;
66 if (ppvObj != NULL)
67 {
68 *ppvObj = NULL;
69 // Aggregation is not supported in singleton objects.
70 ATLASSERT(pUnkOuter == NULL);
71 if (pUnkOuter != NULL)
72 hRes = CLASS_E_NOAGGREGATION;
73 else
74 {
75 if (m_hrCreate == S_OK && m_spObj == NULL)
76 {
77 Lock();
78 __try
79 {
80 // Fix: The following If statement was moved inside the __try statement.
81 // Did another thread arrive here first?
82 if (m_hrCreate == S_OK && m_spObj == NULL)
83 {
84 // lock the module to indicate activity
85 // (necessary for the monitor shutdown thread to correctly
86 // terminate the module in case when CreateInstance() fails)
87 _pAtlModule->Lock();
88 CComObjectCached<T> *p;
89 m_hrCreate = CComObjectCached<T>::CreateInstance(&p);
90 if (SUCCEEDED(m_hrCreate))
91 {
92 m_hrCreate = p->QueryInterface(IID_IUnknown, (void**)&m_spObj);
93 if (FAILED(m_hrCreate))
94 {
95 delete p;
96 }
97 }
98 _pAtlModule->Unlock();
99 }
100 }
101 __finally
102 {
103 Unlock();
104 }
105 }
106 if (m_hrCreate == S_OK)
107 {
108 hRes = m_spObj->QueryInterface(riid, ppvObj);
109 }
110 else
111 {
112 hRes = m_hrCreate;
113 }
114 }
115 }
116 return hRes;
117 }
118 HRESULT m_hrCreate;
119 CComPtr<IUnknown> m_spObj;
120};
121
122#endif // !defined (VBOX_WITH_XPCOM)
123
124// macros
125////////////////////////////////////////////////////////////////////////////////
126
127/**
128 * Special version of the Assert macro to be used within VirtualBoxBase
129 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
130 *
131 * In the debug build, this macro is equivalent to Assert.
132 * In the release build, this macro uses |setError (E_FAIL, ...)| to set the
133 * error info from the asserted expression.
134 *
135 * @see VirtualBoxSupportErrorInfoImpl::setError
136 *
137 * @param expr Expression which should be true.
138 */
139#if defined (DEBUG)
140#define ComAssert(expr) Assert (expr)
141#else
142#define ComAssert(expr) \
143 do { \
144 if (!(expr)) \
145 setError (E_FAIL, "Assertion failed: [%s] at '%s' (%d) in %s.\n" \
146 "Please contact the product vendor!", \
147 #expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
148 } while (0)
149#endif
150
151/**
152 * Special version of the AssertMsg macro to be used within VirtualBoxBase
153 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
154 *
155 * See ComAssert for more info.
156 *
157 * @param expr Expression which should be true.
158 * @param a printf argument list (in parenthesis).
159 */
160#if defined (DEBUG)
161#define ComAssertMsg(expr, a) AssertMsg (expr, a)
162#else
163#define ComAssertMsg(expr, a) \
164 do { \
165 if (!(expr)) \
166 setError (E_FAIL, "Assertion failed: [%s] at '%s' (%d) in %s.\n" \
167 "%s.\n" \
168 "Please contact the product vendor!", \
169 #expr, __FILE__, __LINE__, __PRETTY_FUNCTION__, Utf8StrFmt a .raw()); \
170 } while (0)
171#endif
172
173/**
174 * Special version of the AssertRC macro to be used within VirtualBoxBase
175 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
176 *
177 * See ComAssert for more info.
178 *
179 * @param vrc VBox status code.
180 */
181#if defined (DEBUG)
182#define ComAssertRC(vrc) AssertRC (vrc)
183#else
184#define ComAssertRC(vrc) ComAssertMsgRC (vrc, ("%Vra", 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 (VBOX_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 (!VBOX_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 (!VBOX_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 (!VBOX_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 (!VBOX_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 (!VBOX_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 (!VBOX_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/// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
360/**
361 * Checks whether this object is ready or not. Objects are typically ready
362 * after they are successfully created by their parent objects and become
363 * not ready when the respective parent itsef becomes not ready or gets
364 * destroyed while a reference to the child is still held by the caller
365 * (which prevents it from destruction).
366 *
367 * When this object is not ready, the macro sets error info and returns
368 * E_UNEXPECTED (the translatable error message is defined in null context).
369 * Otherwise, the macro does nothing.
370 *
371 * This macro <b>must</b> be used at the beginning of all interface methods
372 * (right after entering the class lock) in classes derived from both
373 * VirtualBoxBase and VirtualBoxSupportErrorInfoImpl.
374 */
375#define CHECK_READY() \
376 do { \
377 if (!isReady()) \
378 return setError (E_UNEXPECTED, tr ("The object is not ready")); \
379 } while (0)
380
381/**
382 * Declares an empty construtor and destructor for the given class.
383 * This is useful to prevent the compiler from generating the default
384 * ctor and dtor, which in turn allows to use forward class statements
385 * (instead of including their header files) when declaring data members of
386 * non-fundamental types with constructors (which are always called implicitly
387 * by constructors and by the destructor of the class).
388 *
389 * This macro is to be palced within (the public section of) the class
390 * declaration. Its counterpart, DEFINE_EMPTY_CTOR_DTOR, must be placed
391 * somewhere in one of the translation units (usually .cpp source files).
392 *
393 * @param cls class to declare a ctor and dtor for
394 */
395#define DECLARE_EMPTY_CTOR_DTOR(cls) cls(); ~cls();
396
397/**
398 * Defines an empty construtor and destructor for the given class.
399 * See DECLARE_EMPTY_CTOR_DTOR for more info.
400 */
401#define DEFINE_EMPTY_CTOR_DTOR(cls) \
402 cls::cls () {}; cls::~cls () {};
403
404////////////////////////////////////////////////////////////////////////////////
405
406namespace stdx
407{
408 /**
409 * A wrapper around the container that owns pointers it stores.
410 *
411 * @note
412 * Ownership is recognized only when destructing the container!
413 * Pointers are not deleted when erased using erase() etc.
414 *
415 * @param container
416 * class that meets Container requirements (for example, an instance of
417 * std::list<>, std::vector<> etc.). The given class must store
418 * pointers (for example, std::list <MyType *>).
419 */
420 template <typename container>
421 class ptr_container : public container
422 {
423 public:
424 ~ptr_container()
425 {
426 for (typename container::iterator it = container::begin();
427 it != container::end();
428 ++ it)
429 delete (*it);
430 }
431 };
432}
433
434////////////////////////////////////////////////////////////////////////////////
435
436class ATL_NO_VTABLE VirtualBoxBaseNEXT_base
437#if !defined (VBOX_WITH_XPCOM)
438 : public CComObjectRootEx <CComMultiThreadModel>
439#else
440 : public CComObjectRootEx
441#endif
442 , public Lockable
443{
444public:
445
446 enum State { NotReady, Ready, InInit, InUninit, InitFailed, Limited };
447
448protected:
449
450 VirtualBoxBaseNEXT_base();
451 virtual ~VirtualBoxBaseNEXT_base();
452
453public:
454
455 // util::Lockable interface
456 virtual RWLockHandle *lockHandle() const;
457
458 /**
459 * Virtual unintialization method.
460 * Must be called by all implementations (COM classes) when the last
461 * reference to the object is released, before calling the destructor.
462 * Also, this method is called automatically by the uninit() method of the
463 * parent of this object, when this object is a dependent child of a class
464 * derived from VirtualBoxBaseWithChildren (@sa
465 * VirtualBoxBaseWithChildren::addDependentChild).
466 */
467 virtual void uninit() {}
468
469 virtual HRESULT addCaller (State *aState = NULL, bool aLimited = false);
470 virtual void releaseCaller();
471
472 /**
473 * Adds a limited caller. This method is equivalent to doing
474 * <tt>addCaller (aState, true)</tt>, but it is preferred because
475 * provides better self-descriptiveness. See #addCaller() for more info.
476 */
477 HRESULT addLimitedCaller (State *aState = NULL)
478 {
479 return addCaller (aState, true /* aLimited */);
480 }
481
482 /**
483 * Smart class that automatically increases the number of callers of the
484 * given VirtualBoxBase object when an instance is constructed and decreases
485 * it back when the created instance goes out of scope (i.e. gets destroyed).
486 *
487 * If #rc() returns a failure after the instance creation, it means that
488 * the managed VirtualBoxBase object is not Ready, or in any other invalid
489 * state, so that the caller must not use the object and can return this
490 * failed result code to the upper level.
491 *
492 * See VirtualBoxBase::addCaller(), VirtualBoxBase::addLimitedCaller() and
493 * VirtualBoxBase::releaseCaller() for more details about object callers.
494 *
495 * @param aLimited |false| if this template should use
496 * VirtualiBoxBase::addCaller() calls to add callers, or
497 * |true| if VirtualiBoxBase::addLimitedCaller() should be
498 * used.
499 *
500 * @note It is preferrable to use the AutoCaller and AutoLimitedCaller
501 * classes than specify the @a aLimited argument, for better
502 * self-descriptiveness.
503 */
504 template <bool aLimited>
505 class AutoCallerBase
506 {
507 public:
508
509 /**
510 * Increases the number of callers of the given object
511 * by calling VirtualBoxBase::addCaller().
512 *
513 * @param aObj Object to add a caller to. If NULL, this
514 * instance is effectively turned to no-op (where
515 * rc() will return S_OK and state() will be
516 * NotReady).
517 */
518 AutoCallerBase (VirtualBoxBaseNEXT_base *aObj)
519 : mObj (aObj)
520 , mRC (S_OK)
521 , mState (NotReady)
522 {
523 if (mObj)
524 mRC = mObj->addCaller (&mState, aLimited);
525 }
526
527 /**
528 * If the number of callers was successfully increased,
529 * decreases it using VirtualBoxBase::releaseCaller(), otherwise
530 * does nothing.
531 */
532 ~AutoCallerBase()
533 {
534 if (mObj && SUCCEEDED (mRC))
535 mObj->releaseCaller();
536 }
537
538 /**
539 * Stores the result code returned by VirtualBoxBase::addCaller()
540 * after instance creation or after the last #add() call. A successful
541 * result code means the number of callers was successfully increased.
542 */
543 HRESULT rc() const { return mRC; }
544
545 /**
546 * Returns |true| if |SUCCEEDED (rc())| is |true|, for convenience.
547 * |true| means the number of callers was successfully increased.
548 */
549 bool isOk() const { return SUCCEEDED (mRC); }
550
551 /**
552 * Stores the object state returned by VirtualBoxBase::addCaller()
553 * after instance creation or after the last #add() call.
554 */
555 State state() const { return mState; }
556
557 /**
558 * Temporarily decreases the number of callers of the managed object.
559 * May only be called if #isOk() returns |true|. Note that #rc() will
560 * return E_FAIL after this method succeeds.
561 */
562 void release()
563 {
564 Assert (SUCCEEDED (mRC));
565 if (SUCCEEDED (mRC))
566 {
567 if (mObj)
568 mObj->releaseCaller();
569 mRC = E_FAIL;
570 }
571 }
572
573 /**
574 * Restores the number of callers decreased by #release(). May only
575 * be called after #release().
576 */
577 void add()
578 {
579 Assert (!SUCCEEDED (mRC));
580 if (mObj && !SUCCEEDED (mRC))
581 mRC = mObj->addCaller (&mState, aLimited);
582 }
583
584 private:
585
586 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (AutoCallerBase)
587 DECLARE_CLS_NEW_DELETE_NOOP (AutoCallerBase)
588
589 VirtualBoxBaseNEXT_base *mObj;
590 HRESULT mRC;
591 State mState;
592 };
593
594 /**
595 * Smart class that automatically increases the number of normal
596 * (non-limited) callers of the given VirtualBoxBase object when an
597 * instance is constructed and decreases it back when the created instance
598 * goes out of scope (i.e. gets destroyed).
599 *
600 * A typical usage pattern to declare a normal method of some object
601 * (i.e. a method that is valid only when the object provides its
602 * full functionality) is:
603 * <code>
604 * STDMETHODIMP Component::Foo()
605 * {
606 * AutoCaller autoCaller (this);
607 * CheckComRCReturnRC (autoCaller.rc());
608 * ...
609 * </code>
610 *
611 * Using this class is equivalent to using the AutoCallerBase template
612 * with the @a aLimited argument set to |false|, but this class is
613 * preferred because provides better self-descriptiveness.
614 *
615 * See AutoCallerBase for more information about auto caller functionality.
616 */
617 typedef AutoCallerBase <false> AutoCaller;
618
619 /**
620 * Smart class that automatically increases the number of limited callers
621 * of the given VirtualBoxBase object when an instance is constructed and
622 * decreases it back when the created instance goes out of scope (i.e.
623 * gets destroyed).
624 *
625 * A typical usage pattern to declare a limited method of some object
626 * (i.e. a method that is valid even if the object doesn't provide its
627 * full functionality) is:
628 * <code>
629 * STDMETHODIMP Component::Bar()
630 * {
631 * AutoLimitedCaller autoCaller (this);
632 * CheckComRCReturnRC (autoCaller.rc());
633 * ...
634 * </code>
635 *
636 * Using this class is equivalent to using the AutoCallerBase template
637 * with the @a aLimited argument set to |true|, but this class is
638 * preferred because provides better self-descriptiveness.
639 *
640 * See AutoCallerBase for more information about auto caller functionality.
641 */
642 typedef AutoCallerBase <true> AutoLimitedCaller;
643
644protected:
645
646 /**
647 * Smart class to enclose the state transition NotReady->InInit->Ready.
648 *
649 * Instances must be created at the beginning of init() methods of
650 * VirtualBoxBase subclasses as a stack-based variable using |this| pointer
651 * as the argument. When this variable is created it automatically places
652 * the object to the InInit state.
653 *
654 * When the created variable goes out of scope (i.e. gets destroyed),
655 * depending on the success status of this initialization span, it either
656 * places the object to the Ready state or calls the object's
657 * VirtualBoxBase::uninit() method which is supposed to place the object
658 * back to the NotReady state using the AutoUninitSpan class.
659 *
660 * The initial success status of the initialization span is determined by
661 * the @a aSuccess argument of the AutoInitSpan constructor (|false| by
662 * default). Inside the initialization span, the success status can be set
663 * to |true| using #setSucceeded() or to |false| using #setFailed(). Please
664 * don't forget to set the correct success status before letting the
665 * AutoInitSpan variable go out of scope (for example, by performing an
666 * early return from the init() method)!
667 *
668 * Note that if an instance of this class gets constructed when the
669 * object is in the state other than NotReady, #isOk() returns |false| and
670 * methods of this class do nothing: the state transition is not performed.
671 *
672 * A typical usage pattern is:
673 * <code>
674 * HRESULT Component::init()
675 * {
676 * AutoInitSpan autoInitSpan (this);
677 * AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
678 * ...
679 * if (FAILED (rc))
680 * return rc;
681 * ...
682 * if (SUCCEEDED (rc))
683 * autoInitSpan.setSucceeded();
684 * return rc;
685 * }
686 * </code>
687 *
688 * @note Never create instances of this class outside init() methods of
689 * VirtualBoxBase subclasses and never pass anything other than |this| as
690 * the argument to the constructor!
691 */
692 class AutoInitSpan
693 {
694 public:
695
696 enum Status { Failed = 0x0, Succeeded = 0x1, Limited = 0x2 };
697
698 AutoInitSpan (VirtualBoxBaseNEXT_base *aObj, Status aStatus = Failed);
699 ~AutoInitSpan();
700
701 /**
702 * Returns |true| if this instance has been created at the right moment
703 * (when the object was in the NotReady state) and |false| otherwise.
704 */
705 bool isOk() const { return mOk; }
706
707 /**
708 * Sets the initialization status to Succeeded to indicates successful
709 * initialization. The AutoInitSpan destructor will place the managed
710 * VirtualBoxBase object to the Ready state.
711 */
712 void setSucceeded() { mStatus = Succeeded; }
713
714 /**
715 * Sets the initialization status to Succeeded to indicate limited
716 * (partly successful) initialization. The AutoInitSpan destructor will
717 * place the managed VirtualBoxBase object to the Limited state.
718 */
719 void setLimited() { mStatus = Limited; }
720
721 /**
722 * Sets the initialization status to Failure to indicates failed
723 * initialization. The AutoInitSpan destructor will place the managed
724 * VirtualBoxBase object to the InitFailed state and will automatically
725 * call its uninit() method which is supposed to place the object back
726 * to the NotReady state using AutoUninitSpan.
727 */
728 void setFailed() { mStatus = Failed; }
729
730 /** Returns the current initialization status. */
731 Status status() { return mStatus; }
732
733 private:
734
735 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (AutoInitSpan)
736 DECLARE_CLS_NEW_DELETE_NOOP (AutoInitSpan)
737
738 VirtualBoxBaseNEXT_base *mObj;
739 Status mStatus : 3; // must be at least total number of bits + 1 (sign)
740 bool mOk : 1;
741 };
742
743 /**
744 * Smart class to enclose the state transition Limited->InInit->Ready.
745 *
746 * Instances must be created at the beginning of methods of VirtualBoxBase
747 * subclasses that try to re-initialize the object to bring it to the
748 * Ready state (full functionality) after partial initialization
749 * (limited functionality)>, as a stack-based variable using |this| pointer
750 * as the argument. When this variable is created it automatically places
751 * the object to the InInit state.
752 *
753 * When the created variable goes out of scope (i.e. gets destroyed),
754 * depending on the success status of this initialization span, it either
755 * places the object to the Ready state or brings it back to the Limited
756 * state.
757 *
758 * The initial success status of the re-initialization span is |false|.
759 * In order to make it successful, #setSucceeded() must be called before
760 * the instance is destroyed.
761 *
762 * Note that if an instance of this class gets constructed when the
763 * object is in the state other than Limited, #isOk() returns |false| and
764 * methods of this class do nothing: the state transition is not performed.
765 *
766 * A typical usage pattern is:
767 * <code>
768 * HRESULT Component::reinit()
769 * {
770 * AutoReadySpan autoReadySpan (this);
771 * AssertReturn (autoReadySpan.isOk(), E_UNEXPECTED);
772 * ...
773 * if (FAILED (rc))
774 * return rc;
775 * ...
776 * if (SUCCEEDED (rc))
777 * autoReadySpan.setSucceeded();
778 * return rc;
779 * }
780 * </code>
781 *
782 * @note Never create instances of this class outside re-initialization
783 * methods of VirtualBoxBase subclasses and never pass anything other than
784 * |this| as the argument to the constructor!
785 */
786 class AutoReadySpan
787 {
788 public:
789
790 AutoReadySpan (VirtualBoxBaseNEXT_base *aObj);
791 ~AutoReadySpan();
792
793 /**
794 * Returns |true| if this instance has been created at the right moment
795 * (when the object was in the Limited state) and |false| otherwise.
796 */
797 bool isOk() const { return mOk; }
798
799 /**
800 * Sets the re-initialization status to Succeeded to indicates
801 * successful re-initialization. The AutoReadySpan destructor will
802 * place the managed VirtualBoxBase object to the Ready state.
803 */
804 void setSucceeded() { mSucceeded = true; }
805
806 private:
807
808 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (AutoReadySpan)
809 DECLARE_CLS_NEW_DELETE_NOOP (AutoReadySpan)
810
811 VirtualBoxBaseNEXT_base *mObj;
812 bool mSucceeded : 1;
813 bool mOk : 1;
814 };
815
816 /**
817 * Smart class to enclose the state transition Ready->InUnnit->NotReady or
818 * InitFailed->InUnnit->NotReady.
819 *
820 * Must be created at the beginning of uninit() methods of VirtualBoxBase
821 * subclasses as a stack-based variable using |this| pointer as the argument.
822 * When this variable is created it automatically places the object to the
823 * InUninit state, unless it is already in the NotReady state as indicated
824 * by #uninitDone() returning |true|. In the latter case, the uninit()
825 * method must immediately return because there should be nothing to
826 * uninitialize.
827 *
828 * When this variable goes out of scope (i.e. gets destroyed), it places
829 * the object to the NotReady state.
830 *
831 * A typical usage pattern is:
832 * <code>
833 * void Component::uninit()
834 * {
835 * AutoUninitSpan autoUninitSpan (this);
836 * if (autoUninitSpan.uninitDone())
837 * retrun;
838 * ...
839 * </code>
840 *
841 * @note Never create instances of this class outside uninit() methods and
842 * never pass anything other than |this| as the argument to the constructor!
843 */
844 class AutoUninitSpan
845 {
846 public:
847
848 AutoUninitSpan (VirtualBoxBaseNEXT_base *aObj);
849 ~AutoUninitSpan();
850
851 /** |true| when uninit() is called as a result of init() failure */
852 bool initFailed() { return mInitFailed; }
853
854 /** |true| when uninit() has already been called (so the object is NotReady) */
855 bool uninitDone() { return mUninitDone; }
856
857 private:
858
859 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (AutoUninitSpan)
860 DECLARE_CLS_NEW_DELETE_NOOP (AutoUninitSpan)
861
862 VirtualBoxBaseNEXT_base *mObj;
863 bool mInitFailed : 1;
864 bool mUninitDone : 1;
865 };
866
867 /**
868 * Returns a lock handle used to protect the primary state fields (used by
869 * #addCaller(), AutoInitSpan, AutoUninitSpan, etc.). Only intended to be
870 * used for similar purposes in subclasses. WARNING: NO any other locks may
871 * be requested while holding this lock!
872 */
873 WriteLockHandle *stateLockHandle() { return &mStateLock; }
874
875private:
876
877 void setState (State aState)
878 {
879 Assert (mState != aState);
880 mState = aState;
881 mStateChangeThread = RTThreadSelf();
882 }
883
884 /** Primary state of this object */
885 State mState;
886 /** Thread that caused the last state change */
887 RTTHREAD mStateChangeThread;
888 /** Total number of active calls to this object */
889 unsigned mCallers;
890 /** Semaphore posted when the number of callers drops to zero */
891 RTSEMEVENT mZeroCallersSem;
892 /** Semaphore posted when the object goes from InInit some other state */
893 RTSEMEVENTMULTI mInitDoneSem;
894 /** Number of threads waiting for mInitDoneSem */
895 unsigned mInitDoneSemUsers;
896
897 /** Protects access to state related data members */
898 WriteLockHandle mStateLock;
899
900 /** User-level object lock for subclasses */
901 mutable RWLockHandle *mObjectLock;
902};
903
904/**
905 * This macro adds the error info support to methods of the VirtualBoxBase
906 * class (by overriding them). Place it to the public section of the
907 * VirtualBoxBase subclass and the following methods will set the extended
908 * error info in case of failure instead of just returning the result code:
909 *
910 * <ul>
911 * <li>VirtualBoxBase::addCaller()
912 * </ul>
913 *
914 * @note The given VirtualBoxBase subclass must also inherit from both
915 * VirtualBoxSupportErrorInfoImpl and VirtualBoxSupportTranslation templates!
916 *
917 * @param C VirtualBoxBase subclass to add the error info support to
918 */
919#define VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(C) \
920 virtual HRESULT addCaller (VirtualBoxBaseNEXT_base::State *aState = NULL, \
921 bool aLimited = false) \
922 { \
923 VirtualBoxBaseNEXT_base::State state; \
924 HRESULT rc = VirtualBoxBaseNEXT_base::addCaller (&state, aLimited); \
925 if (FAILED (rc)) \
926 { \
927 if (state == VirtualBoxBaseNEXT_base::Limited) \
928 rc = setError (rc, tr ("The object functonality is limited")); \
929 else \
930 rc = setError (rc, tr ("The object is not ready")); \
931 } \
932 if (aState) \
933 *aState = state; \
934 return rc; \
935 } \
936
937////////////////////////////////////////////////////////////////////////////////
938
939/// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
940class ATL_NO_VTABLE VirtualBoxBase : public VirtualBoxBaseNEXT_base
941//#if !defined (VBOX_WITH_XPCOM)
942// : public CComObjectRootEx<CComMultiThreadModel>
943//#else
944// : public CComObjectRootEx
945//#endif
946{
947
948public:
949 VirtualBoxBase()
950 {
951 mReady = false;
952 }
953 virtual ~VirtualBoxBase()
954 {
955 }
956
957 /**
958 * Virtual unintialization method. Called during parent object's
959 * uninitialization, if the given subclass instance is a dependent child of
960 * a class dervived from VirtualBoxBaseWithChildren (@sa
961 * VirtualBoxBaseWithChildren::addDependentChild). In this case, this
962 * method's impelemtation must call setReady (false),
963 */
964 virtual void uninit() {}
965
966
967 // sets the ready state of the object
968 void setReady(bool isReady)
969 {
970 mReady = isReady;
971 }
972 // get the ready state of the object
973 bool isReady()
974 {
975 return mReady;
976 }
977
978 static const char *translate (const char *context, const char *sourceText,
979 const char *comment = 0);
980
981private:
982
983 // flag determining whether an object is ready
984 // for usage, i.e. methods may be called
985 bool mReady;
986 // mutex semaphore to lock the object
987};
988
989/**
990 * Temporary class to disable deprecated methods of VirtualBoxBase.
991 * Can be used as a base for components that are completely switched to
992 * the new locking scheme (VirtualBoxBaseNEXT_base).
993 *
994 * @todo remove after we switch to VirtualBoxBaseNEXT completely.
995 */
996class VirtualBoxBaseNEXT : public VirtualBoxBase
997{
998private:
999
1000 void lock();
1001 void unlock();
1002 void setReady (bool isReady);
1003 bool isReady();
1004};
1005
1006////////////////////////////////////////////////////////////////////////////////
1007
1008/** Helper for VirtualBoxSupportTranslation */
1009class VirtualBoxSupportTranslationBase
1010{
1011protected:
1012 static bool cutClassNameFrom__PRETTY_FUNCTION__ (char *prettyFunctionName);
1013};
1014
1015/**
1016 * This template implements the NLS string translation support for the
1017 * given class by providing a #tr() function.
1018 *
1019 * @param C class that needs to support the string translation
1020 *
1021 * @note
1022 * Every class that wants to use the #tr() function in its own methods must
1023 * inherit from this template, regardless of whether its base class (if any)
1024 * inherits from it or not! Otherwise, the translation service will not
1025 * work correctly. However, the declaration of the resulting class must
1026 * contain the VIRTUALBOXSUPPORTTRANSLATION_OVERRIDE(<ClassName>) macro
1027 * if one of its base classes also inherits from this template (to resolve
1028 * the ambiguity of the #tr() function).
1029 */
1030template <class C>
1031class VirtualBoxSupportTranslation : virtual protected VirtualBoxSupportTranslationBase
1032{
1033public:
1034
1035 /**
1036 * Translates the given text string according to the currently installed
1037 * translation table and current context, which is determined by the
1038 * class name. See VirtualBoxBase::translate() for more info.
1039 *
1040 * @param sourceText the string to translate
1041 * @param comment the comment to the string (NULL means no comment)
1042 *
1043 * @return
1044 * the translated version of the source string in UTF-8 encoding,
1045 * or the source string itself if the translation is not found in
1046 * the current context.
1047 */
1048 inline static const char *tr (const char *sourceText, const char *comment = 0)
1049 {
1050 return VirtualBoxBase::translate (getClassName(), sourceText, comment);
1051 }
1052
1053protected:
1054
1055 static const char *getClassName()
1056 {
1057 static char fn [sizeof (__PRETTY_FUNCTION__) + 1];
1058 if (!className)
1059 {
1060 strcpy (fn, __PRETTY_FUNCTION__);
1061 cutClassNameFrom__PRETTY_FUNCTION__ (fn);
1062 className = fn;
1063 }
1064 return className;
1065 }
1066
1067private:
1068
1069 static const char *className;
1070};
1071
1072template <class C>
1073const char *VirtualBoxSupportTranslation <C>::className = NULL;
1074
1075/**
1076 * This macro must be invoked inside the public section of the declaration of
1077 * the class inherited from the VirtualBoxSupportTranslation template, in case
1078 * when one of its other base classes also inherits from that template. This is
1079 * necessary to resolve the ambiguity of the #tr() function.
1080 *
1081 * @param C class that inherits from the VirtualBoxSupportTranslation template
1082 * more than once (through its other base clases)
1083 */
1084#define VIRTUALBOXSUPPORTTRANSLATION_OVERRIDE(C) \
1085 inline static const char *tr (const char *sourceText, const char *comment = 0) \
1086 { \
1087 return VirtualBoxSupportTranslation <C>::tr (sourceText, comment); \
1088 }
1089
1090/**
1091 * A dummy macro that is used to shut down Qt's lupdate tool warnings
1092 * in some situations. This macro needs to be present inside (better at the
1093 * very beginning) of the declaration of the class that inherits from
1094 * VirtualBoxSupportTranslation template, to make lupdate happy.
1095 */
1096#define Q_OBJECT
1097
1098////////////////////////////////////////////////////////////////////////////////
1099
1100/**
1101 * Helper for the VirtualBoxSupportErrorInfoImpl template.
1102 */
1103class VirtualBoxSupportErrorInfoImplBase
1104{
1105 static HRESULT setErrorInternal (HRESULT aResultCode, const GUID &aIID,
1106 const Bstr &aComponent, const Bstr &aText,
1107 bool aWarning, bool aLogIt);
1108
1109protected:
1110
1111 /**
1112 * The MultiResult class is a com::LWResult enhancement that also acts as a
1113 * switch to turn on multi-error mode for #setError() or #setWarning()
1114 * calls.
1115 *
1116 * When an instance of this class is created, multi-error mode is turned on
1117 * for the current thread and the turn-on counter is increased by one. In
1118 * multi-error mode, a call to #setError() or #setWarning() does not
1119 * overwrite the current error or warning info object possibly set on the
1120 * current thread by other method calls, but instead it stores this old
1121 * object in the IVirtualBoxErrorInfo::next attribute of the new error
1122 * object being set.
1123 *
1124 * This way, error/warning objects are stacked together and form a chain of
1125 * errors where the most recent error is the first one retrieved by the
1126 * calling party, the preceeding error is what the
1127 * IVirtualBoxErrorInfo::next attribute of the first error points to, and so
1128 * on, upto the first error or warning occured which is the last in the
1129 * chain. See IVirtualBoxErrorInfo documentation for more info.
1130 *
1131 * When the instance of the MultiResult class goes out of scope and gets
1132 * destroyed, it automatically decreases the turn-on counter by one. If
1133 * the counter drops to zero, multi-error mode for the current thread is
1134 * turned off and the thread switches back to single-error mode where every
1135 * next error or warning object overwrites the previous one.
1136 *
1137 * Note that the caller of a COM methid uses a non-S_OK result code to
1138 * decide if the method has returned an error (negative codes) or a warning
1139 * (positive non-zero codes) and will query extended error info only in
1140 * these two cases. However, since multi-error mode implies that the method
1141 * doesn't return control return to the caller immediately after the first
1142 * error or warning but continues its execution, the functionality provided
1143 * by the base com::LWResult class becomes very useful because it allows to
1144 * preseve the error or the warning result code even if it is later assigned
1145 * a S_OK value multiple times. See com::LWResult for details.
1146 *
1147 * Here is the typical usage pattern:
1148 * <code>
1149
1150 HRESULT Bar::method()
1151 {
1152 // assume multi-errors are turned off here...
1153
1154 if (something)
1155 {
1156 // Turn on multi-error mode and make sure severity is preserved
1157 MultiResult rc = foo->method1();
1158
1159 // return on fatal error, but continue on warning or on success
1160 CheckComRCReturnRC (rc);
1161
1162 rc = foo->method2();
1163 // no matter what result, stack it and continue
1164
1165 // ...
1166
1167 // return the last worst result code (it will be preserved even if
1168 // foo->method2() returns S_OK.
1169 return rc;
1170 }
1171
1172 // multi-errors are turned off here again...
1173
1174 return S_OK;
1175 }
1176
1177 * </code>
1178 *
1179 *
1180 * @note This class is intended to be instantiated on the stack, therefore
1181 * You cannot create them using new(). Although it is possible to copy
1182 * instances of MultiResult or return them by value, please never do
1183 * that as it is breaks the class semantics (and will assert);
1184 */
1185 class MultiResult : public com::LWResult
1186 {
1187 public:
1188
1189 /**
1190 * @see com::LWResult::LWResult().
1191 */
1192 MultiResult (HRESULT aRC = E_FAIL) : LWResult (aRC) { init(); }
1193
1194 MultiResult (const MultiResult &aThat) : LWResult (aThat)
1195 {
1196 /* We need this copy constructor only for GCC that wants to have
1197 * it in case of expressions like |MultiResult rc = E_FAIL;|. But
1198 * we assert since the optimizer should actually avoid the
1199 * temporary and call the other constructor directly istead. */
1200 AssertFailed();
1201 init();
1202 }
1203
1204 ~MultiResult();
1205
1206 MultiResult &operator= (HRESULT aRC)
1207 {
1208 com::LWResult::operator= (aRC);
1209 return *this;
1210 }
1211
1212 MultiResult &operator= (const MultiResult &aThat)
1213 {
1214 /* We need this copy constructor only for GCC that wants to have
1215 * it in case of expressions like |MultiResult rc = E_FAIL;|. But
1216 * we assert since the optimizer should actually avoid the
1217 * temporary and call the other constructor directly istead. */
1218 AssertFailed();
1219 com::LWResult::operator= (aThat);
1220 return *this;
1221 }
1222
1223 private:
1224
1225 DECLARE_CLS_NEW_DELETE_NOOP (MultiResult)
1226
1227 void init();
1228
1229 static RTTLS sCounter;
1230
1231 friend class VirtualBoxSupportErrorInfoImplBase;
1232 };
1233
1234 static HRESULT setError (HRESULT aResultCode, const GUID &aIID,
1235 const Bstr &aComponent,
1236 const Bstr &aText,
1237 bool aLogIt = true)
1238 {
1239 return setErrorInternal (aResultCode, aIID, aComponent, aText,
1240 false /* aWarning */, aLogIt);
1241 }
1242
1243 static HRESULT setWarning (HRESULT aResultCode, const GUID &aIID,
1244 const Bstr &aComponent,
1245 const Bstr &aText)
1246 {
1247 return setErrorInternal (aResultCode, aIID, aComponent, aText,
1248 true /* aWarning */, true /* aLogIt */);
1249 }
1250
1251 static HRESULT setError (HRESULT aResultCode, const GUID &aIID,
1252 const Bstr &aComponent,
1253 const char *aText, va_list aArgs, bool aLogIt = true)
1254 {
1255 return setErrorInternal (aResultCode, aIID, aComponent,
1256 Utf8StrFmtVA (aText, aArgs),
1257 false /* aWarning */, aLogIt);
1258 }
1259
1260 static HRESULT setWarning (HRESULT aResultCode, const GUID &aIID,
1261 const Bstr &aComponent,
1262 const char *aText, va_list aArgs)
1263 {
1264 return setErrorInternal (aResultCode, aIID, aComponent,
1265 Utf8StrFmtVA (aText, aArgs),
1266 true /* aWarning */, true /* aLogIt */);
1267 }
1268};
1269
1270/**
1271 * This template implements ISupportErrorInfo for the given component class
1272 * and provides the #setError() method to conveniently set the error information
1273 * from within interface methods' implementations.
1274 *
1275 * On Windows, the template argument must define a COM interface map using
1276 * BEGIN_COM_MAP / END_COM_MAP macros and this map must contain a
1277 * COM_INTERFACE_ENTRY(ISupportErrorInfo) definition. All interface entries
1278 * that follow it will be considered to support IErrorInfo, i.e. the
1279 * InterfaceSupportsErrorInfo() implementation will return S_OK for the
1280 * corresponding IID.
1281 *
1282 * On all platforms, the template argument must also define the following
1283 * method: |public static const wchar_t *C::getComponentName()|. See
1284 * #setError (HRESULT, const char *, ...) for a description on how it is
1285 * used.
1286 *
1287 * @param C
1288 * component class that implements one or more COM interfaces
1289 * @param I
1290 * default interface for the component. This interface's IID is used
1291 * by the shortest form of #setError, for convenience.
1292 */
1293template <class C, class I>
1294class ATL_NO_VTABLE VirtualBoxSupportErrorInfoImpl
1295 : protected VirtualBoxSupportErrorInfoImplBase
1296#if !defined (VBOX_WITH_XPCOM)
1297 , public ISupportErrorInfo
1298#else
1299#endif
1300{
1301public:
1302
1303#if !defined (VBOX_WITH_XPCOM)
1304 STDMETHOD(InterfaceSupportsErrorInfo) (REFIID riid)
1305 {
1306 const _ATL_INTMAP_ENTRY* pEntries = C::_GetEntries();
1307 Assert (pEntries);
1308 if (!pEntries)
1309 return S_FALSE;
1310
1311 BOOL bSupports = FALSE;
1312 BOOL bISupportErrorInfoFound = FALSE;
1313
1314 while (pEntries->pFunc != NULL && !bSupports)
1315 {
1316 if (!bISupportErrorInfoFound)
1317 {
1318 // skip the com map entries until ISupportErrorInfo is found
1319 bISupportErrorInfoFound =
1320 InlineIsEqualGUID (*(pEntries->piid), IID_ISupportErrorInfo);
1321 }
1322 else
1323 {
1324 // look for the requested interface in the rest of the com map
1325 bSupports = InlineIsEqualGUID (*(pEntries->piid), riid);
1326 }
1327 pEntries++;
1328 }
1329
1330 Assert (bISupportErrorInfoFound);
1331
1332 return bSupports ? S_OK : S_FALSE;
1333 }
1334#endif // !defined (VBOX_WITH_XPCOM)
1335
1336protected:
1337
1338 /**
1339 * Sets the error information for the current thread.
1340 * This information can be retrieved by a caller of an interface method
1341 * using IErrorInfo on Windows or nsIException on Linux, or the cross-platform
1342 * IVirtualBoxErrorInfo interface that provides extended error info (only
1343 * for components from the VirtualBox COM library). Alternatively, the
1344 * platform-independent class com::ErrorInfo (defined in VBox[XP]COM.lib)
1345 * can be used to retrieve error info in a convenient way.
1346 *
1347 * It is assumed that the interface method that uses this function returns
1348 * an unsuccessful result code to the caller (otherwise, there is no reason
1349 * for the caller to try to retrieve error info after method invocation).
1350 *
1351 * Here is a table of correspondence between this method's arguments
1352 * and IErrorInfo/nsIException/IVirtualBoxErrorInfo attributes/methods:
1353 *
1354 * argument IErrorInfo nsIException IVirtualBoxErrorInfo
1355 * ----------------------------------------------------------------
1356 * resultCode -- result resultCode
1357 * iid GetGUID -- interfaceID
1358 * component GetSource -- component
1359 * text GetDescription message text
1360 *
1361 * This method is rarely needs to be used though. There are more convenient
1362 * overloaded versions, that automatically substitute some arguments
1363 * taking their values from the template parameters. See
1364 * #setError (HRESULT, const char *, ...) for an example.
1365 *
1366 * @param aResultCode result (error) code, must not be S_OK
1367 * @param aIID IID of the intrface that defines the error
1368 * @param aComponent name of the component that generates the error
1369 * @param aText error message (must not be null), an RTStrPrintf-like
1370 * format string in UTF-8 encoding
1371 * @param ... list of arguments for the format string
1372 *
1373 * @return
1374 * the error argument, for convenience, If an error occures while
1375 * creating error info itself, that error is returned instead of the
1376 * error argument.
1377 */
1378 static HRESULT setError (HRESULT aResultCode, const GUID &aIID,
1379 const wchar_t *aComponent,
1380 const char *aText, ...)
1381 {
1382 va_list args;
1383 va_start (args, aText);
1384 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError
1385 (aResultCode, aIID, aComponent, aText, args, true /* aLogIt */);
1386 va_end (args);
1387 return rc;
1388 }
1389
1390 /**
1391 * This method is the same as #setError() except that it makes sure @a
1392 * aResultCode doesn't have the error severty bit (31) set when passed
1393 * down to the created IVirtualBoxErrorInfo object.
1394 *
1395 * The error severity bit is always cleared by this call, thereofe you can
1396 * use ordinary E_XXX result code constancs, for convenience. However, this
1397 * behavior may be non-stanrard on some COM platforms.
1398 */
1399 static HRESULT setWarning (HRESULT aResultCode, const GUID &aIID,
1400 const wchar_t *aComponent,
1401 const char *aText, ...)
1402 {
1403 va_list args;
1404 va_start (args, aText);
1405 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setWarning
1406 (aResultCode, aIID, aComponent, aText, args);
1407 va_end (args);
1408 return rc;
1409 }
1410
1411 /**
1412 * Sets the error information for the current thread.
1413 * A convenience method that automatically sets the default interface
1414 * ID (taken from the I template argument) and the component name
1415 * (a value of C::getComponentName()).
1416 *
1417 * See #setError (HRESULT, const GUID &, const wchar_t *, const char *text, ...)
1418 * for details.
1419 *
1420 * This method is the most common (and convenient) way to set error
1421 * information from within interface methods. A typical pattern of usage
1422 * is looks like this:
1423 *
1424 * <code>
1425 * return setError (E_FAIL, "Terrible Error");
1426 * </code>
1427 * or
1428 * <code>
1429 * HRESULT rc = setError (E_FAIL, "Terrible Error");
1430 * ...
1431 * return rc;
1432 * </code>
1433 */
1434 static HRESULT setError (HRESULT aResultCode, const char *aText, ...)
1435 {
1436 va_list args;
1437 va_start (args, aText);
1438 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError
1439 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText, args, true /* aLogIt */);
1440 va_end (args);
1441 return rc;
1442 }
1443
1444 /**
1445 * This method is the same as #setError() except that it makes sure @a
1446 * aResultCode doesn't have the error severty bit (31) set when passed
1447 * down to the created IVirtualBoxErrorInfo object.
1448 *
1449 * The error severity bit is always cleared by this call, thereofe you can
1450 * use ordinary E_XXX result code constancs, for convenience. However, this
1451 * behavior may be non-stanrard on some COM platforms.
1452 */
1453 static HRESULT setWarning (HRESULT aResultCode, const char *aText, ...)
1454 {
1455 va_list args;
1456 va_start (args, aText);
1457 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setWarning
1458 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText, args);
1459 va_end (args);
1460 return rc;
1461 }
1462
1463 /**
1464 * Sets the error information for the current thread, va_list variant.
1465 * A convenience method that automatically sets the default interface
1466 * ID (taken from the I template argument) and the component name
1467 * (a value of C::getComponentName()).
1468 *
1469 * See #setError (HRESULT, const GUID &, const wchar_t *, const char *text, ...)
1470 * and #setError (HRESULT, const char *, ...) for details.
1471 */
1472 static HRESULT setErrorV (HRESULT aResultCode, const char *aText,
1473 va_list aArgs)
1474 {
1475 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError
1476 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText, aArgs, true /* aLogIt */);
1477 return rc;
1478 }
1479
1480 /**
1481 * This method is the same as #setErrorV() except that it makes sure @a
1482 * aResultCode doesn't have the error severty bit (31) set when passed
1483 * down to the created IVirtualBoxErrorInfo object.
1484 *
1485 * The error severity bit is always cleared by this call, thereofe you can
1486 * use ordinary E_XXX result code constancs, for convenience. However, this
1487 * behavior may be non-stanrard on some COM platforms.
1488 */
1489 static HRESULT setWarningV (HRESULT aResultCode, const char *aText,
1490 va_list aArgs)
1491 {
1492 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setWarning
1493 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText, aArgs);
1494 return rc;
1495 }
1496
1497 /**
1498 * Sets the error information for the current thread, BStr variant.
1499 * A convenience method that automatically sets the default interface
1500 * ID (taken from the I template argument) and the component name
1501 * (a value of C::getComponentName()).
1502 *
1503 * This method is preferred iy you have a ready (translated and formatted)
1504 * Bstr string, because it omits an extra conversion Utf8Str -> Bstr.
1505 *
1506 * See #setError (HRESULT, const GUID &, const wchar_t *, const char *text, ...)
1507 * and #setError (HRESULT, const char *, ...) for details.
1508 */
1509 static HRESULT setErrorBstr (HRESULT aResultCode, const Bstr &aText)
1510 {
1511 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError
1512 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText, true /* aLogIt */);
1513 return rc;
1514 }
1515
1516 /**
1517 * This method is the same as #setErrorBstr() except that it makes sure @a
1518 * aResultCode doesn't have the error severty bit (31) set when passed
1519 * down to the created IVirtualBoxErrorInfo object.
1520 *
1521 * The error severity bit is always cleared by this call, thereofe you can
1522 * use ordinary E_XXX result code constancs, for convenience. However, this
1523 * behavior may be non-stanrard on some COM platforms.
1524 */
1525 static HRESULT setWarningBstr (HRESULT aResultCode, const Bstr &aText)
1526 {
1527 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setWarning
1528 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText);
1529 return rc;
1530 }
1531
1532 /**
1533 * Sets the error information for the current thread.
1534 * A convenience method that automatically sets the component name
1535 * (a value of C::getComponentName()), but allows to specify the interface
1536 * id manually.
1537 *
1538 * See #setError (HRESULT, const GUID &, const wchar_t *, const char *text, ...)
1539 * for details.
1540 */
1541 static HRESULT setError (HRESULT aResultCode, const GUID &aIID,
1542 const char *aText, ...)
1543 {
1544 va_list args;
1545 va_start (args, aText);
1546 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError
1547 (aResultCode, aIID, C::getComponentName(), aText, args, true /* aLogIt */);
1548 va_end (args);
1549 return rc;
1550 }
1551
1552 /**
1553 * This method is the same as #setError() except that it makes sure @a
1554 * aResultCode doesn't have the error severty bit (31) set when passed
1555 * down to the created IVirtualBoxErrorInfo object.
1556 *
1557 * The error severity bit is always cleared by this call, thereofe you can
1558 * use ordinary E_XXX result code constancs, for convenience. However, this
1559 * behavior may be non-stanrard on some COM platforms.
1560 */
1561 static HRESULT setWarning (HRESULT aResultCode, const GUID &aIID,
1562 const char *aText, ...)
1563 {
1564 va_list args;
1565 va_start (args, aText);
1566 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setWarning
1567 (aResultCode, aIID, C::getComponentName(), aText, args);
1568 va_end (args);
1569 return rc;
1570 }
1571
1572 /**
1573 * Sets the error information for the current thread but doesn't put
1574 * anything in the release log. This is very useful for avoiding
1575 * harmless error from causing confusion.
1576 *
1577 * It is otherwise identical to #setError (HRESULT, const char *text, ...).
1578 */
1579 static HRESULT setErrorNoLog (HRESULT aResultCode, const char *aText, ...)
1580 {
1581 va_list args;
1582 va_start (args, aText);
1583 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError
1584 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText, args, false /* aLogIt */);
1585 va_end (args);
1586 return rc;
1587 }
1588
1589private:
1590
1591};
1592
1593////////////////////////////////////////////////////////////////////////////////
1594
1595/**
1596 * Base class to track VirtualBoxBase chlidren of the component.
1597 *
1598 * This class is a preferrable VirtualBoxBase replacement for components
1599 * that operate with collections of child components. It gives two useful
1600 * possibilities:
1601 *
1602 * <ol><li>
1603 * Given an IUnknown instance, it's possible to quickly determine
1604 * whether this instance represents a child object created by the given
1605 * component, and if so, get a valid VirtualBoxBase pointer to the child
1606 * object. The returned pointer can be then safely casted to the
1607 * actual class of the child object (to get access to its "internal"
1608 * non-interface methods) provided that no other child components implement
1609 * the same initial interface IUnknown is queried from.
1610 * </li><li>
1611 * When the parent object uninitializes itself, it can easily unintialize
1612 * all its VirtualBoxBase derived children (using their
1613 * VirtualBoxBase::uninit() implementations). This is done simply by
1614 * calling the #uninitDependentChildren() method.
1615 * </li></ol>
1616 *
1617 * In order to let the above work, the following must be done:
1618 * <ol><li>
1619 * When a child object is initialized, it calls #addDependentChild() of
1620 * its parent to register itself within the list of dependent children.
1621 * </li><li>
1622 * When a child object it is uninitialized, it calls #removeDependentChild()
1623 * to unregister itself. This must be done <b>after</b> the child has called
1624 * setReady(false) to indicate it is no more valid, and <b>not</b> from under
1625 * the child object's lock. Note also, that the first action the child's
1626 * uninit() implementation must do is to check for readiness after acquiring
1627 * the object's lock and return immediately if not ready.
1628 * </li></ol>
1629 *
1630 * Children added by #addDependentChild() are <b>weakly</b> referenced
1631 * (i.e. AddRef() is not called), so when a child is externally destructed
1632 * (i.e. its reference count goes to zero), it will automatically remove
1633 * itself from a map of dependent children, provided that it follows the
1634 * rules described here.
1635 *
1636 * @note
1637 * Because of weak referencing, deadlocks and assertions are very likely
1638 * if #addDependentChild() or #removeDependentChild() are used incorrectly
1639 * (called at inappropriate times). Check the above rules once more.
1640 *
1641 * @deprecated Use VirtualBoxBaseWithChildrenNEXT for new classes.
1642 */
1643class VirtualBoxBaseWithChildren : public VirtualBoxBase
1644{
1645public:
1646
1647 VirtualBoxBaseWithChildren()
1648 : mUninitDoneSem (NIL_RTSEMEVENT), mChildrenLeft (0)
1649 {}
1650
1651 virtual ~VirtualBoxBaseWithChildren()
1652 {}
1653
1654 /**
1655 * Adds the given child to the map of dependent children.
1656 * Intended to be called from the child's init() method,
1657 * from under the child's lock.
1658 *
1659 * @param C the child object to add (must inherit VirtualBoxBase AND
1660 * implement some interface)
1661 */
1662 template <class C>
1663 void addDependentChild (C *child)
1664 {
1665 AssertReturn (child, (void) 0);
1666 addDependentChild (child, child);
1667 }
1668
1669 /**
1670 * Removes the given child from the map of dependent children.
1671 * Must be called <b>after<b> the child has called setReady(false), and
1672 * <b>not</b> from under the child object's lock.
1673 *
1674 * @param C the child object to remove (must inherit VirtualBoxBase AND
1675 * implement some interface)
1676 */
1677 template <class C>
1678 void removeDependentChild (C *child)
1679 {
1680 AssertReturn (child, (void) 0);
1681 /// @todo (r=dmik) the below check (and the relevant comment above)
1682 // seems to be not necessary any more once we completely switch to
1683 // the NEXT locking scheme. This requires altering removeDependentChild()
1684 // and uninitDependentChildren() as well (due to the new state scheme,
1685 // there is a separate mutex for state transition, so calling the
1686 // child's uninit() from under the children map lock should not produce
1687 // dead-locks any more).
1688 Assert (!child->isWriteLockOnCurrentThread() || child->lockHandle() == lockHandle());
1689 removeDependentChild (ComPtr <IUnknown> (child));
1690 }
1691
1692protected:
1693
1694 void uninitDependentChildren();
1695
1696 VirtualBoxBase *getDependentChild (const ComPtr <IUnknown> &unk);
1697
1698private:
1699
1700 void addDependentChild (const ComPtr <IUnknown> &unk, VirtualBoxBase *child);
1701 void removeDependentChild (const ComPtr <IUnknown> &unk);
1702
1703 typedef std::map <IUnknown *, VirtualBoxBase *> DependentChildren;
1704 DependentChildren mDependentChildren;
1705
1706 WriteLockHandle mMapLock;
1707
1708 RTSEMEVENT mUninitDoneSem;
1709 unsigned mChildrenLeft;
1710};
1711
1712////////////////////////////////////////////////////////////////////////////////
1713
1714/**
1715 *
1716 * Base class to track VirtualBoxBaseNEXT chlidren of the component.
1717 *
1718 * This class is a preferrable VirtualBoxBase replacement for components that
1719 * operate with collections of child components. It gives two useful
1720 * possibilities:
1721 *
1722 * <ol><li>
1723 * Given an IUnknown instance, it's possible to quickly determine
1724 * whether this instance represents a child object created by the given
1725 * component, and if so, get a valid VirtualBoxBase pointer to the child
1726 * object. The returned pointer can be then safely casted to the
1727 * actual class of the child object (to get access to its "internal"
1728 * non-interface methods) provided that no other child components implement
1729 * the same initial interface IUnknown is queried from.
1730 * </li><li>
1731 * When the parent object uninitializes itself, it can easily unintialize
1732 * all its VirtualBoxBase derived children (using their
1733 * VirtualBoxBase::uninit() implementations). This is done simply by
1734 * calling the #uninitDependentChildren() method.
1735 * </li></ol>
1736 *
1737 * In order to let the above work, the following must be done:
1738 * <ol><li>
1739 * When a child object is initialized, it calls #addDependentChild() of
1740 * its parent to register itself within the list of dependent children.
1741 * </li><li>
1742 * When a child object it is uninitialized, it calls
1743 * #removeDependentChild() to unregister itself. Since the child's
1744 * uninitialization may originate both from this method and from the child
1745 * itself calling its uninit() on another thread at the same time, please
1746 * make sure that #removeDependentChild() is called:
1747 * <ul><li>
1748 * after the child has successfully entered AutoUninitSpan -- to make
1749 * sure this method is called only once for the given child object
1750 * transitioning from Ready to NotReady. A failure to do so will at
1751 * least likely cause an assertion ("Failed to remove the child from
1752 * the map").
1753 * </li><li>
1754 * outside the child object's lock -- to avoid guaranteed deadlocks
1755 * caused by different lock order: (child_lock, map_lock) in uninit()
1756 * and (map_lock, child_lock) in this method.
1757 * </li></ul>
1758 * </li></ol>
1759 *
1760 * Note that children added by #addDependentChild() are <b>weakly</b> referenced
1761 * (i.e. AddRef() is not called), so when a child object is deleted externally
1762 * (because it's reference count goes to zero), it will automatically remove
1763 * itself from the map of dependent children provided that it follows the rules
1764 * described here.
1765 *
1766 * @note Once again: because of weak referencing, deadlocks and assertions are
1767 * very likely if #addDependentChild() or #removeDependentChild() are used
1768 * incorrectly (called at inappropriate times). Check the above rules once
1769 * more.
1770 *
1771 * @todo This is a VirtualBoxBaseWithChildren equivalent that uses the
1772 * VirtualBoxBaseNEXT implementation. Will completely supercede
1773 * VirtualBoxBaseWithChildren after the old VirtualBoxBase implementation
1774 * has gone.
1775 */
1776class VirtualBoxBaseWithChildrenNEXT : public VirtualBoxBaseNEXT
1777{
1778public:
1779
1780 VirtualBoxBaseWithChildrenNEXT()
1781 : mUninitDoneSem (NIL_RTSEMEVENT), mChildrenLeft (0)
1782 {}
1783
1784 virtual ~VirtualBoxBaseWithChildrenNEXT()
1785 {}
1786
1787 /**
1788 * Adds the given child to the map of dependent children.
1789 *
1790 * Typically called from the child's init() method, from within the
1791 * AutoInitSpan scope. Otherwise, VirtualBoxBase::AutoCaller must be
1792 * used on @a aChild to make sure it is not uninitialized during this
1793 * method's call.
1794 *
1795 * @param aChild Child object to add (must inherit VirtualBoxBase AND
1796 * implement some interface).
1797 */
1798 template <class C>
1799 void addDependentChild (C *aChild)
1800 {
1801 AssertReturnVoid (aChild);
1802 doAddDependentChild (ComPtr <IUnknown> (aChild), aChild);
1803 }
1804
1805 /**
1806 * Removes the given child from the map of dependent children.
1807 *
1808 * Make sure this method is called after the child has successfully entered
1809 * AutoUninitSpan and outside the child lock.
1810 *
1811 * If called not from within the AutoUninitSpan scope,
1812 * VirtualBoxBase::AutoCaller must be used on @a aChild to make sure it is
1813 * not uninitialized during this method's call.
1814 *
1815 * @param aChild Child object to remove (must inherit VirtualBoxBase AND
1816 * implement some interface).
1817 */
1818 template <class C>
1819 void removeDependentChild (C *aChild)
1820 {
1821 AssertReturnVoid (aChild);
1822 Assert (!aChild->isWriteLockOnCurrentThread());
1823 doRemoveDependentChild (ComPtr <IUnknown> (aChild));
1824 }
1825
1826protected:
1827
1828 void uninitDependentChildren();
1829
1830 VirtualBoxBaseNEXT *getDependentChild (const ComPtr <IUnknown> &aUnk);
1831
1832private:
1833
1834 /// @todo temporarily reinterpret VirtualBoxBase * as VirtualBoxBaseNEXT *
1835 // until ported HardDisk and Progress to the new scheme.
1836 void doAddDependentChild (IUnknown *aUnk, VirtualBoxBase *aChild)
1837 {
1838 doAddDependentChild (aUnk,
1839 reinterpret_cast <VirtualBoxBaseNEXT *> (aChild));
1840 }
1841
1842 void doAddDependentChild (IUnknown *aUnk, VirtualBoxBaseNEXT *aChild);
1843 void doRemoveDependentChild (IUnknown *aUnk);
1844
1845 typedef std::map <IUnknown *, VirtualBoxBaseNEXT *> DependentChildren;
1846 DependentChildren mDependentChildren;
1847
1848 RTSEMEVENT mUninitDoneSem;
1849 size_t mChildrenLeft;
1850
1851 /* Protects all the fields above */
1852 RWLockHandle mMapLock;
1853};
1854
1855////////////////////////////////////////////////////////////////////////////////
1856
1857/**
1858 * Base class to track component's children of some particular type.
1859 *
1860 * This class is similar to VirtualBoxBaseWithChildren, with the exception
1861 * that all children must be of the same type. For this reason, it's not
1862 * necessary to use a map to store children, so a list is used instead.
1863 *
1864 * As opposed to VirtualBoxBaseWithChildren, children added by
1865 * #addDependentChild() are <b>strongly</b> referenced, so that they cannot
1866 * be externally destructed until #removeDependentChild() is called.
1867 * For this reason, strict rules of calling #removeDependentChild() don't
1868 * apply to instances of this class -- it can be called anywhere in the
1869 * child's uninit() implementation.
1870 *
1871 * @param C type of child objects (must inherit VirtualBoxBase AND
1872 * implement some interface)
1873 *
1874 * @deprecated Use VirtualBoxBaseWithTypedChildrenNEXT for new classes.
1875 */
1876template <class C>
1877class VirtualBoxBaseWithTypedChildren : public VirtualBoxBase
1878{
1879public:
1880
1881 typedef std::list <ComObjPtr <C> > DependentChildren;
1882
1883 VirtualBoxBaseWithTypedChildren() : mInUninit (false) {}
1884
1885 virtual ~VirtualBoxBaseWithTypedChildren() {}
1886
1887 /**
1888 * Adds the given child to the list of dependent children.
1889 * Must be called from the child's init() method,
1890 * from under the child's lock.
1891 *
1892 * @param C the child object to add (must inherit VirtualBoxBase AND
1893 * implement some interface)
1894 */
1895 void addDependentChild (C *child)
1896 {
1897 AssertReturn (child, (void) 0);
1898
1899 AutoWriteLock alock (mMapLock);
1900 if (mInUninit)
1901 return;
1902
1903 mDependentChildren.push_back (child);
1904 }
1905
1906 /**
1907 * Removes the given child from the list of dependent children.
1908 * Must be called from the child's uninit() method,
1909 * under the child's lock.
1910 *
1911 * @param C the child object to remove (must inherit VirtualBoxBase AND
1912 * implement some interface)
1913 */
1914 void removeDependentChild (C *child)
1915 {
1916 AssertReturn (child, (void) 0);
1917
1918 AutoWriteLock alock (mMapLock);
1919 if (mInUninit)
1920 return;
1921
1922 mDependentChildren.remove (child);
1923 }
1924
1925protected:
1926
1927 /**
1928 * Returns an internal lock handle to lock the list of children
1929 * returned by #dependentChildren() using AutoWriteLock:
1930 * <code>
1931 * AutoWriteLock alock (dependentChildrenLock());
1932 * </code>
1933 */
1934 RWLockHandle *dependentChildrenLock() const { return &mMapLock; }
1935
1936 /**
1937 * Returns the read-only list of all dependent children.
1938 * @note
1939 * Access the returned list (iterate, get size etc.) only after
1940 * doing |AutoWriteLock alock (dependentChildrenLock());|!
1941 */
1942 const DependentChildren &dependentChildren() const { return mDependentChildren; }
1943
1944 /**
1945 * Uninitializes all dependent children registered with #addDependentChild().
1946 *
1947 * @note
1948 * This method will call uninit() methods of children. If these methods
1949 * access the parent object, uninitDependentChildren() must be called
1950 * either at the beginning of the parent uninitialization sequence (when
1951 * it is still operational) or after setReady(false) is called to
1952 * indicate the parent is out of action.
1953 */
1954 void uninitDependentChildren()
1955 {
1956 AutoWriteLock alock (this);
1957 AutoWriteLock mapLock (mMapLock);
1958
1959 if (mDependentChildren.size())
1960 {
1961 // set flag to ignore #removeDependentChild() called from child->uninit()
1962 mInUninit = true;
1963
1964 // leave the locks to let children waiting for #removeDependentChild() run
1965 mapLock.leave();
1966 alock.leave();
1967
1968 for (typename DependentChildren::iterator it = mDependentChildren.begin();
1969 it != mDependentChildren.end(); ++ it)
1970 {
1971 C *child = (*it);
1972 Assert (child);
1973 if (child)
1974 child->uninit();
1975 }
1976 mDependentChildren.clear();
1977
1978 alock.enter();
1979 mapLock.enter();
1980
1981 mInUninit = false;
1982 }
1983 }
1984
1985 /**
1986 * Removes (detaches) all dependent children registered with
1987 * #addDependentChild(), without uninitializing them.
1988 *
1989 * @note This method must be called from under the main object's lock
1990 */
1991 void removeDependentChildren()
1992 {
1993 AutoWriteLock alock (mMapLock);
1994 mDependentChildren.clear();
1995 }
1996
1997private:
1998
1999 DependentChildren mDependentChildren;
2000
2001 bool mInUninit;
2002 mutable RWLockHandle mMapLock;
2003};
2004
2005////////////////////////////////////////////////////////////////////////////////
2006
2007/**
2008 * Base class to track component's chlidren of the particular type.
2009 *
2010 * This class is similar to VirtualBoxBaseWithChildren, with the exception that
2011 * all children must be of the same type. For this reason, it's not necessary to
2012 * use a map to store children, so a list is used instead.
2013 *
2014 * As opposed to VirtualBoxBaseWithChildren, children added by
2015 * #addDependentChild() are <b>strongly</b> referenced, so that they cannot be
2016 * externally deleted until #removeDependentChild() is called. For this
2017 * reason, strict rules of calling #removeDependentChild() don't apply to
2018 * instances of this class -- it can be called anywhere in the child's uninit()
2019 * implementation.
2020 *
2021 * @param C Type of child objects (must inherit VirtualBoxBase AND implementsome
2022 * interface).
2023 *
2024 * @todo This is a VirtualBoxBaseWithChildren equivalent that uses the
2025 * VirtualBoxBaseNEXT implementation. Will completely supercede
2026 * VirtualBoxBaseWithChildren after the old VirtualBoxBase implementation
2027 * has gone.
2028 */
2029template <class C>
2030class VirtualBoxBaseWithTypedChildrenNEXT : public VirtualBoxBaseNEXT
2031{
2032public:
2033
2034 typedef std::list <ComObjPtr <C> > DependentChildren;
2035
2036 VirtualBoxBaseWithTypedChildrenNEXT() : mInUninit (false) {}
2037
2038 virtual ~VirtualBoxBaseWithTypedChildrenNEXT() {}
2039
2040 /**
2041 * Adds the given child to the list of dependent children.
2042 *
2043 * VirtualBoxBase::AutoCaller must be used on @a aChild to make sure it is
2044 * not uninitialized during this method's call.
2045 *
2046 * @param aChild Child object to add (must inherit VirtualBoxBase AND
2047 * implement some interface).
2048 */
2049 void addDependentChild (C *aChild)
2050 {
2051 AssertReturnVoid (aChild);
2052
2053 AutoWriteLock alock (mMapLock);
2054 if (mInUninit)
2055 return;
2056
2057 mDependentChildren.push_back (aChild);
2058 }
2059
2060 /**
2061 * Removes the given child from the list of dependent children.
2062 *
2063 * VirtualBoxBase::AutoCaller must be used on @a aChild to make sure it is
2064 * not uninitialized during this method's call.
2065 *
2066 * @param aChild the child object to remove (must inherit VirtualBoxBase
2067 * AND implement some interface).
2068 */
2069 void removeDependentChild (C *aChild)
2070 {
2071 AssertReturnVoid (aChild);
2072
2073 AutoWriteLock alock (mMapLock);
2074 if (mInUninit)
2075 return;
2076
2077 mDependentChildren.remove (aChild);
2078 }
2079
2080protected:
2081
2082 /**
2083 * Returns an internal lock handle used to lock the list of children
2084 * returned by #dependentChildren(). This lock is to be used by
2085 * AutoWriteLock as follows:
2086 * <code>
2087 * AutoWriteLock alock (dependentChildrenLock());
2088 * </code>
2089 */
2090 RWLockHandle *dependentChildrenLock() const { return &mMapLock; }
2091
2092 /**
2093 * Returns the read-only list of all dependent children.
2094 *
2095 * @note Access the returned list (iterate, get size etc.) only after doing
2096 * AutoWriteLock alock (dependentChildrenLock())!
2097 */
2098 const DependentChildren &dependentChildren() const { return mDependentChildren; }
2099
2100 void uninitDependentChildren();
2101
2102 /**
2103 * Removes (detaches) all dependent children registered with
2104 * #addDependentChild(), without uninitializing them.
2105 *
2106 * @note This method must be called from under the main object's lock.
2107 */
2108 void removeDependentChildren()
2109 {
2110 /// @todo why?..
2111 AssertReturnVoid (isWriteLockOnCurrentThread());
2112
2113 AutoWriteLock alock (mMapLock);
2114 mDependentChildren.clear();
2115 }
2116
2117private:
2118
2119 DependentChildren mDependentChildren;
2120
2121 bool mInUninit;
2122
2123 /* Protects the two fields above */
2124 mutable RWLockHandle mMapLock;
2125};
2126
2127////////////////////////////////////////////////////////////////////////////////
2128
2129/// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
2130/**
2131 * Simple template that manages data structure allocation/deallocation
2132 * and supports data pointer sharing (the instance that shares the pointer is
2133 * not responsible for memory deallocation as opposed to the instance that
2134 * owns it).
2135 */
2136template <class D>
2137class Shareable
2138{
2139public:
2140
2141 Shareable() : mData (NULL), mIsShared (FALSE) {}
2142 ~Shareable() { free(); }
2143
2144 void allocate() { attach (new D); }
2145
2146 virtual void free() {
2147 if (mData) {
2148 if (!mIsShared)
2149 delete mData;
2150 mData = NULL;
2151 mIsShared = false;
2152 }
2153 }
2154
2155 void attach (D *data) {
2156 AssertMsg (data, ("new data must not be NULL"));
2157 if (data && mData != data) {
2158 if (mData && !mIsShared)
2159 delete mData;
2160 mData = data;
2161 mIsShared = false;
2162 }
2163 }
2164
2165 void attach (Shareable &data) {
2166 AssertMsg (
2167 data.mData == mData || !data.mIsShared,
2168 ("new data must not be shared")
2169 );
2170 if (this != &data && !data.mIsShared) {
2171 attach (data.mData);
2172 data.mIsShared = true;
2173 }
2174 }
2175
2176 void share (D *data) {
2177 AssertMsg (data, ("new data must not be NULL"));
2178 if (mData != data) {
2179 if (mData && !mIsShared)
2180 delete mData;
2181 mData = data;
2182 mIsShared = true;
2183 }
2184 }
2185
2186 void share (const Shareable &data) { share (data.mData); }
2187
2188 void attachCopy (const D *data) {
2189 AssertMsg (data, ("data to copy must not be NULL"));
2190 if (data)
2191 attach (new D (*data));
2192 }
2193
2194 void attachCopy (const Shareable &data) {
2195 attachCopy (data.mData);
2196 }
2197
2198 virtual D *detach() {
2199 D *d = mData;
2200 mData = NULL;
2201 mIsShared = false;
2202 return d;
2203 }
2204
2205 D *data() const {
2206 return mData;
2207 }
2208
2209 D *operator->() const {
2210 AssertMsg (mData, ("data must not be NULL"));
2211 return mData;
2212 }
2213
2214 bool isNull() const { return mData == NULL; }
2215 bool operator!() const { return isNull(); }
2216
2217 bool isShared() const { return mIsShared; }
2218
2219protected:
2220
2221 D *mData;
2222 bool mIsShared;
2223};
2224
2225/// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
2226/**
2227 * Simple template that enhances Shareable<> and supports data
2228 * backup/rollback/commit (using the copy constructor of the managed data
2229 * structure).
2230 */
2231template <class D>
2232class Backupable : public Shareable <D>
2233{
2234public:
2235
2236 Backupable() : Shareable <D> (), mBackupData (NULL) {}
2237
2238 void free()
2239 {
2240 AssertMsg (this->mData || !mBackupData, ("backup must be NULL if data is NULL"));
2241 rollback();
2242 Shareable <D>::free();
2243 }
2244
2245 D *detach()
2246 {
2247 AssertMsg (this->mData || !mBackupData, ("backup must be NULL if data is NULL"));
2248 rollback();
2249 return Shareable <D>::detach();
2250 }
2251
2252 void share (const Backupable &data)
2253 {
2254 AssertMsg (!data.isBackedUp(), ("data to share must not be backed up"));
2255 if (!data.isBackedUp())
2256 Shareable <D>::share (data.mData);
2257 }
2258
2259 /**
2260 * Stores the current data pointer in the backup area, allocates new data
2261 * using the copy constructor on current data and makes new data active.
2262 */
2263 void backup()
2264 {
2265 AssertMsg (this->mData, ("data must not be NULL"));
2266 if (this->mData && !mBackupData)
2267 {
2268 mBackupData = this->mData;
2269 this->mData = new D (*mBackupData);
2270 }
2271 }
2272
2273 /**
2274 * Deletes new data created by #backup() and restores previous data pointer
2275 * stored in the backup area, making it active again.
2276 */
2277 void rollback()
2278 {
2279 if (this->mData && mBackupData)
2280 {
2281 delete this->mData;
2282 this->mData = mBackupData;
2283 mBackupData = NULL;
2284 }
2285 }
2286
2287 /**
2288 * Commits current changes by deleting backed up data and clearing up the
2289 * backup area. The new data pointer created by #backup() remains active
2290 * and becomes the only managed pointer.
2291 *
2292 * This method is much faster than #commitCopy() (just a single pointer
2293 * assignment operation), but makes the previous data pointer invalid
2294 * (because it is freed). For this reason, this method must not be
2295 * used if it's possible that data managed by this instance is shared with
2296 * some other Shareable instance. See #commitCopy().
2297 */
2298 void commit()
2299 {
2300 if (this->mData && mBackupData)
2301 {
2302 if (!this->mIsShared)
2303 delete mBackupData;
2304 mBackupData = NULL;
2305 this->mIsShared = false;
2306 }
2307 }
2308
2309 /**
2310 * Commits current changes by assigning new data to the previous data
2311 * pointer stored in the backup area using the assignment operator.
2312 * New data is deleted, the backup area is cleared and the previous data
2313 * pointer becomes active and the only managed pointer.
2314 *
2315 * This method is slower than #commit(), but it keeps the previous data
2316 * pointer valid (i.e. new data is copied to the same memory location).
2317 * For that reason it's safe to use this method on instances that share
2318 * managed data with other Shareable instances.
2319 */
2320 void commitCopy()
2321 {
2322 if (this->mData && mBackupData)
2323 {
2324 *mBackupData = *(this->mData);
2325 delete this->mData;
2326 this->mData = mBackupData;
2327 mBackupData = NULL;
2328 }
2329 }
2330
2331 void assignCopy (const D *data)
2332 {
2333 AssertMsg (this->mData, ("data must not be NULL"));
2334 AssertMsg (data, ("data to copy must not be NULL"));
2335 if (this->mData && data)
2336 {
2337 if (!mBackupData)
2338 {
2339 mBackupData = this->mData;
2340 this->mData = new D (*data);
2341 }
2342 else
2343 *this->mData = *data;
2344 }
2345 }
2346
2347 void assignCopy (const Backupable &data)
2348 {
2349 assignCopy (data.mData);
2350 }
2351
2352 bool isBackedUp() const
2353 {
2354 return mBackupData != NULL;
2355 }
2356
2357 bool hasActualChanges() const
2358 {
2359 AssertMsg (this->mData, ("data must not be NULL"));
2360 return this->mData != NULL && mBackupData != NULL &&
2361 !(*this->mData == *mBackupData);
2362 }
2363
2364 D *backedUpData() const
2365 {
2366 return mBackupData;
2367 }
2368
2369protected:
2370
2371 D *mBackupData;
2372};
2373
2374#if defined VBOX_MAIN_SETTINGS_ADDONS
2375
2376/**
2377 * Settinsg API additions.
2378 */
2379namespace settings
2380{
2381
2382/// @todo once string data in Bstr and Utf8Str is auto_ref_ptr, enable the
2383/// code below
2384
2385#if 0
2386
2387/** Specialization of FromString for Bstr. */
2388template<> com::Bstr FromString <com::Bstr> (const char *aValue);
2389
2390#endif
2391
2392/** Specialization of ToString for Bstr. */
2393template<> stdx::char_auto_ptr
2394ToString <com::Bstr> (const com::Bstr &aValue, unsigned int aExtra);
2395
2396/** Specialization of FromString for Guid. */
2397template<> com::Guid FromString <com::Guid> (const char *aValue);
2398
2399/** Specialization of ToString for Guid. */
2400template<> stdx::char_auto_ptr
2401ToString <com::Guid> (const com::Guid &aValue, unsigned int aExtra);
2402
2403} /* namespace settings */
2404
2405#endif /* VBOX_MAIN_SETTINGS_ADDONS */
2406
2407#endif // ____H_VIRTUALBOXBASEIMPL
Note: See TracBrowser for help on using the repository browser.

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