VirtualBox

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

Last change on this file since 6111 was 6076, checked in by vboxsync, 17 years ago

Merged dmik/s2 branch (r25959:26751) to the trunk.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 69.4 KB
Line 
1/** @file
2 *
3 * VirtualBox COM base classes definition
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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
18#ifndef ____H_VIRTUALBOXBASEIMPL
19#define ____H_VIRTUALBOXBASEIMPL
20
21#include "VBox/com/string.h"
22#include "VBox/com/Guid.h"
23#include "VBox/com/ptr.h"
24#include "VBox/com/ErrorInfo.h"
25
26#include "VBox/com/VirtualBox.h"
27
28#include <VBox/settings.h>
29
30#include "AutoLock.h"
31
32using namespace com;
33using util::AutoLock;
34using util::AutoReaderLock;
35using util::AutoMultiLock;
36
37#include <iprt/cdefs.h>
38#include <iprt/critsect.h>
39
40#include <list>
41#include <map>
42
43#if defined (RT_OS_WINDOWS)
44
45#include <atlcom.h>
46
47// use a special version of the singleton class factory,
48// see KB811591 in msdn for more info.
49
50#undef DECLARE_CLASSFACTORY_SINGLETON
51#define DECLARE_CLASSFACTORY_SINGLETON(obj) DECLARE_CLASSFACTORY_EX(CMyComClassFactorySingleton<obj>)
52
53template <class T>
54class CMyComClassFactorySingleton : public CComClassFactory
55{
56public:
57 CMyComClassFactorySingleton() : m_hrCreate(S_OK){}
58 virtual ~CMyComClassFactorySingleton(){}
59 // IClassFactory
60 STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj)
61 {
62 HRESULT hRes = E_POINTER;
63 if (ppvObj != NULL)
64 {
65 *ppvObj = NULL;
66 // Aggregation is not supported in singleton objects.
67 ATLASSERT(pUnkOuter == NULL);
68 if (pUnkOuter != NULL)
69 hRes = CLASS_E_NOAGGREGATION;
70 else
71 {
72 if (m_hrCreate == S_OK && m_spObj == NULL)
73 {
74 Lock();
75 __try
76 {
77 // Fix: The following If statement was moved inside the __try statement.
78 // Did another thread arrive here first?
79 if (m_hrCreate == S_OK && m_spObj == NULL)
80 {
81 // lock the module to indicate activity
82 // (necessary for the monitor shutdown thread to correctly
83 // terminate the module in case when CreateInstance() fails)
84 _pAtlModule->Lock();
85 CComObjectCached<T> *p;
86 m_hrCreate = CComObjectCached<T>::CreateInstance(&p);
87 if (SUCCEEDED(m_hrCreate))
88 {
89 m_hrCreate = p->QueryInterface(IID_IUnknown, (void**)&m_spObj);
90 if (FAILED(m_hrCreate))
91 {
92 delete p;
93 }
94 }
95 _pAtlModule->Unlock();
96 }
97 }
98 __finally
99 {
100 Unlock();
101 }
102 }
103 if (m_hrCreate == S_OK)
104 {
105 hRes = m_spObj->QueryInterface(riid, ppvObj);
106 }
107 else
108 {
109 hRes = m_hrCreate;
110 }
111 }
112 }
113 return hRes;
114 }
115 HRESULT m_hrCreate;
116 CComPtr<IUnknown> m_spObj;
117};
118
119#endif // defined (RT_OS_WINDOWS)
120
121// macros
122////////////////////////////////////////////////////////////////////////////////
123
124/**
125 * Special version of the Assert macro to be used within VirtualBoxBase
126 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
127 *
128 * In the debug build, this macro is equivalent to Assert.
129 * In the release build, this macro uses |setError (E_FAIL, ...)| to set the
130 * error info from the asserted expression.
131 *
132 * @see VirtualBoxSupportErrorInfoImpl::setError
133 *
134 * @param expr Expression which should be true.
135 */
136#if defined (DEBUG)
137#define ComAssert(expr) Assert (expr)
138#else
139#define ComAssert(expr) \
140 do { \
141 if (!(expr)) \
142 setError (E_FAIL, "Assertion failed: [%s] at '%s' (%d) in %s.\n" \
143 "Please contact the product vendor!", \
144 #expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
145 } while (0)
146#endif
147
148/**
149 * Special version of the AssertMsg macro to be used within VirtualBoxBase
150 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
151 *
152 * See ComAssert for more info.
153 *
154 * @param expr Expression which should be true.
155 * @param a printf argument list (in parenthesis).
156 */
157#if defined (DEBUG)
158#define ComAssertMsg(expr, a) AssertMsg (expr, a)
159#else
160#define ComAssertMsg(expr, a) \
161 do { \
162 if (!(expr)) \
163 setError (E_FAIL, "Assertion failed: [%s] at '%s' (%d) in %s.\n" \
164 "%s.\n" \
165 "Please contact the product vendor!", \
166 #expr, __FILE__, __LINE__, __PRETTY_FUNCTION__, Utf8StrFmt a .raw()); \
167 } while (0)
168#endif
169
170/**
171 * Special version of the AssertRC macro to be used within VirtualBoxBase
172 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
173 *
174 * See ComAssert for more info.
175 *
176 * @param vrc VBox status code.
177 */
178#if defined (DEBUG)
179#define ComAssertRC(vrc) AssertRC (vrc)
180#else
181#define ComAssertRC(vrc) ComAssertMsgRC (vrc, ("%Vra", vrc))
182#endif
183
184/**
185 * Special version of the AssertMsgRC macro to be used within VirtualBoxBase
186 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
187 *
188 * See ComAssert for more info.
189 *
190 * @param vrc VBox status code.
191 * @param msg printf argument list (in parenthesis).
192 */
193#if defined (DEBUG)
194#define ComAssertMsgRC(vrc, msg) AssertMsgRC (vrc, msg)
195#else
196#define ComAssertMsgRC(vrc, msg) ComAssertMsg (VBOX_SUCCESS (vrc), msg)
197#endif
198
199
200/**
201 * Special version of the AssertFailed macro to be used within VirtualBoxBase
202 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
203 *
204 * See ComAssert for more info.
205 */
206#if defined (DEBUG)
207#define ComAssertFailed() AssertFailed()
208#else
209#define ComAssertFailed() \
210 do { \
211 setError (E_FAIL, "Assertion failed at '%s' (%d) in %s.\n" \
212 "Please contact the product vendor!", \
213 __FILE__, __LINE__, __PRETTY_FUNCTION__); \
214 } while (0)
215#endif
216
217/**
218 * Special version of the AssertMsgFailed macro to be used within VirtualBoxBase
219 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
220 *
221 * See ComAssert for more info.
222 *
223 * @param a printf argument list (in parenthesis).
224 */
225#if defined (DEBUG)
226#define ComAssertMsgFailed(a) AssertMsgFailed(a)
227#else
228#define ComAssertMsgFailed(a) \
229 do { \
230 setError (E_FAIL, "Assertion failed at '%s' (%d) in %s.\n" \
231 "%s.\n" \
232 "Please contact the product vendor!", \
233 __FILE__, __LINE__, __PRETTY_FUNCTION__, Utf8StrFmt a .raw()); \
234 } while (0)
235#endif
236
237/**
238 * Special version of the ComAssertMsgFailed macro that additionally takes
239 * line number, file and function arguments to inject an assertion position
240 * that differs from the position where this macro is instantiated.
241 *
242 * @param a printf argument list (in parenthesis).
243 * @param file, line, func Line number (int), file and function (const char *).
244 */
245#if defined (DEBUG)
246#define ComAssertMsgFailedPos(a, file, line, func) \
247 do { \
248 AssertMsg1 ((const char *) 0, line, file, func); \
249 AssertMsg2 a; \
250 AssertBreakpoint(); \
251 } while (0)
252#else
253#define ComAssertMsgFailedPos(a, file, line, func) \
254 do { \
255 setError (E_FAIL, \
256 "Assertion failed at '%s' (%d) in %s.\n" \
257 "%s.\n" \
258 "Please contact the product vendor!", \
259 file, line, func, Utf8StrFmt a .raw()); \
260 } while (0)
261#endif
262
263/**
264 * Special version of the AssertComRC macro to be used within VirtualBoxBase
265 * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
266 *
267 * See ComAssert for more info.
268 *
269 * @param rc COM result code
270 */
271#if defined (DEBUG)
272#define ComAssertComRC(rc) AssertComRC (rc)
273#else
274#define ComAssertComRC(rc) ComAssertMsg (SUCCEEDED (rc), ("COM RC = 0x%08X\n", rc))
275#endif
276
277
278/** Special version of ComAssert that returns ret if expr fails */
279#define ComAssertRet(expr, ret) \
280 do { ComAssert (expr); if (!(expr)) return (ret); } while (0)
281/** Special version of ComAssertMsg that returns ret if expr fails */
282#define ComAssertMsgRet(expr, a, ret) \
283 do { ComAssertMsg (expr, a); if (!(expr)) return (ret); } while (0)
284/** Special version of ComAssertRC that returns ret if vrc does not succeed */
285#define ComAssertRCRet(vrc, ret) \
286 do { ComAssertRC (vrc); if (!VBOX_SUCCESS (vrc)) return (ret); } while (0)
287/** Special version of ComAssertMsgRC that returns ret if vrc does not succeed */
288#define ComAssertMsgRCRet(vrc, msg, ret) \
289 do { ComAssertMsgRC (vrc, msg); if (!VBOX_SUCCESS (vrc)) return (ret); } while (0)
290/** Special version of ComAssertFailed that returns ret */
291#define ComAssertFailedRet(ret) \
292 do { ComAssertFailed(); return (ret); } while (0)
293/** Special version of ComAssertMsgFailed that returns ret */
294#define ComAssertMsgFailedRet(msg, ret) \
295 do { ComAssertMsgFailed (msg); return (ret); } while (0)
296/** Special version of ComAssertComRC that returns ret if rc does not succeed */
297#define ComAssertComRCRet(rc, ret) \
298 do { ComAssertComRC (rc); if (!SUCCEEDED (rc)) return (ret); } while (0)
299/** Special version of ComAssertComRC that returns rc if rc does not succeed */
300#define ComAssertComRCRetRC(rc) \
301 do { ComAssertComRC (rc); if (!SUCCEEDED (rc)) return (rc); } while (0)
302
303
304/** Special version of ComAssert that evaulates eval and breaks if expr fails */
305#define ComAssertBreak(expr, eval) \
306 if (1) { ComAssert (expr); if (!(expr)) { eval; break; } } else do {} while (0)
307/** Special version of ComAssertMsg that evaulates eval and breaks if expr fails */
308#define ComAssertMsgBreak(expr, a, eval) \
309 if (1) { ComAssertMsg (expr, a); if (!(expr)) { eval; break; } } else do {} while (0)
310/** Special version of ComAssertRC that evaulates eval and breaks if vrc does not succeed */
311#define ComAssertRCBreak(vrc, eval) \
312 if (1) { ComAssertRC (vrc); if (!VBOX_SUCCESS (vrc)) { eval; break; } } else do {} while (0)
313/** Special version of ComAssertMsgRC that evaulates eval and breaks if vrc does not succeed */
314#define ComAssertMsgRCBreak(vrc, msg, eval) \
315 if (1) { ComAssertMsgRC (vrc, msg); if (!VBOX_SUCCESS (vrc)) { eval; break; } } else do {} while (0)
316/** Special version of ComAssertFailed that evaulates eval and breaks */
317#define ComAssertFailedBreak(eval) \
318 if (1) { ComAssertFailed(); { eval; break; } } else do {} while (0)
319/** Special version of ComAssertMsgFailed that evaulates eval and breaks */
320#define ComAssertMsgFailedBreak(msg, eval) \
321 if (1) { ComAssertMsgFailed (msg); { eval; break; } } else do {} while (0)
322/** Special version of ComAssertComRC that evaulates eval and breaks if rc does not succeed */
323#define ComAssertComRCBreak(rc, eval) \
324 if (1) { ComAssertComRC (rc); if (!SUCCEEDED (rc)) { eval; break; } } else do {} while (0)
325/** Special version of ComAssertComRC that just breaks if rc does not succeed */
326#define ComAssertComRCBreakRC(rc) \
327 if (1) { ComAssertComRC (rc); if (!SUCCEEDED (rc)) { break; } } else do {} while (0)
328
329
330/** Special version of ComAssert that evaulates eval and throws it if expr fails */
331#define ComAssertThrow(expr, eval) \
332 if (1) { ComAssert (expr); if (!(expr)) { throw (eval); } } else do {} while (0)
333/** Special version of ComAssertMsg that evaulates eval and throws it if expr fails */
334#define ComAssertMsgThrow(expr, a, eval) \
335 if (1) { ComAssertMsg (expr, a); if (!(expr)) { throw (eval); } } else do {} while (0)
336/** Special version of ComAssertRC that evaulates eval and throws it if vrc does not succeed */
337#define ComAssertRCThrow(vrc, eval) \
338 if (1) { ComAssertRC (vrc); if (!VBOX_SUCCESS (vrc)) { throw (eval); } } else do {} while (0)
339/** Special version of ComAssertMsgRC that evaulates eval and throws it if vrc does not succeed */
340#define ComAssertMsgRCThrow(vrc, msg, eval) \
341 if (1) { ComAssertMsgRC (vrc, msg); if (!VBOX_SUCCESS (vrc)) { throw (eval); } } else do {} while (0)
342/** Special version of ComAssertFailed that evaulates eval and throws it */
343#define ComAssertFailedThrow(eval) \
344 if (1) { ComAssertFailed(); { throw (eval); } } else do {} while (0)
345/** Special version of ComAssertMsgFailed that evaulates eval and throws it */
346#define ComAssertMsgFailedThrow(msg, eval) \
347 if (1) { ComAssertMsgFailed (msg); { throw (eval); } } else do {} while (0)
348/** Special version of ComAssertComRC that evaulates eval and throws it if rc does not succeed */
349#define ComAssertComRCThrow(rc, eval) \
350 if (1) { ComAssertComRC (rc); if (!SUCCEEDED (rc)) { throw (eval); } } else do {} while (0)
351/** Special version of ComAssertComRC that just throws rc if rc does not succeed */
352#define ComAssertComRCThrowRC(rc) \
353 if (1) { ComAssertComRC (rc); if (!SUCCEEDED (rc)) { throw rc; } } else do {} while (0)
354
355
356/// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
357/**
358 * Checks whether this object is ready or not. Objects are typically ready
359 * after they are successfully created by their parent objects and become
360 * not ready when the respective parent itsef becomes not ready or gets
361 * destroyed while a reference to the child is still held by the caller
362 * (which prevents it from destruction).
363 *
364 * When this object is not ready, the macro sets error info and returns
365 * E_UNEXPECTED (the translatable error message is defined in null context).
366 * Otherwise, the macro does nothing.
367 *
368 * This macro <b>must</b> be used at the beginning of all interface methods
369 * (right after entering the class lock) in classes derived from both
370 * VirtualBoxBase and VirtualBoxSupportErrorInfoImpl.
371 */
372#define CHECK_READY() \
373 do { \
374 if (!isReady()) \
375 return setError (E_UNEXPECTED, tr ("The object is not ready")); \
376 } while (0)
377
378/**
379 * Declares an empty construtor and destructor for the given class.
380 * This is useful to prevent the compiler from generating the default
381 * ctor and dtor, which in turn allows to use forward class statements
382 * (instead of including their header files) when declaring data members of
383 * non-fundamental types with constructors (which are always called implicitly
384 * by constructors and by the destructor of the class).
385 *
386 * This macro is to be palced within (the public section of) the class
387 * declaration. Its counterpart, DEFINE_EMPTY_CTOR_DTOR, must be placed
388 * somewhere in one of the translation units (usually .cpp source files).
389 *
390 * @param cls class to declare a ctor and dtor for
391 */
392#define DECLARE_EMPTY_CTOR_DTOR(cls) cls(); ~cls();
393
394/**
395 * Defines an empty construtor and destructor for the given class.
396 * See DECLARE_EMPTY_CTOR_DTOR for more info.
397 */
398#define DEFINE_EMPTY_CTOR_DTOR(cls) \
399 cls::cls () {}; cls::~cls () {};
400
401////////////////////////////////////////////////////////////////////////////////
402
403namespace stdx
404{
405 /**
406 * A wrapper around the container that owns pointers it stores.
407 *
408 * @note
409 * Ownership is recognized only when destructing the container!
410 * Pointers are not deleted when erased using erase() etc.
411 *
412 * @param container
413 * class that meets Container requirements (for example, an instance of
414 * std::list<>, std::vector<> etc.). The given class must store
415 * pointers (for example, std::list <MyType *>).
416 */
417 template <typename container>
418 class ptr_container : public container
419 {
420 public:
421 ~ptr_container()
422 {
423 for (typename container::iterator it = container::begin();
424 it != container::end();
425 ++ it)
426 delete (*it);
427 }
428 };
429}
430
431////////////////////////////////////////////////////////////////////////////////
432
433class ATL_NO_VTABLE VirtualBoxBaseNEXT_base
434#ifdef RT_OS_WINDOWS
435 : public CComObjectRootEx <CComMultiThreadModel>
436#else
437 : public CComObjectRootEx
438#endif
439 , public AutoLock::Lockable
440{
441public:
442
443 enum State { NotReady, Ready, InInit, InUninit, InitFailed, Limited };
444
445protected:
446
447 VirtualBoxBaseNEXT_base();
448 virtual ~VirtualBoxBaseNEXT_base();
449
450public:
451
452 // AutoLock::Lockable interface
453 virtual AutoLock::Handle *lockHandle() const;
454
455 /**
456 * Virtual unintialization method.
457 * Must be called by all implementations (COM classes) when the last
458 * reference to the object is released, before calling the destructor.
459 * Also, this method is called automatically by the uninit() method of the
460 * parent of this object, when this object is a dependent child of a class
461 * derived from VirtualBoxBaseWithChildren (@sa
462 * VirtualBoxBaseWithChildren::addDependentChild).
463 */
464 virtual void uninit() {}
465
466 virtual HRESULT addCaller (State *aState = NULL, bool aLimited = false);
467 virtual void releaseCaller();
468
469 /**
470 * Adds a limited caller. This method is equivalent to doing
471 * <tt>addCaller (aState, true)</tt>, but it is preferred because
472 * provides better self-descriptiveness. See #addCaller() for more info.
473 */
474 HRESULT addLimitedCaller (State *aState = NULL)
475 {
476 return addCaller (aState, true /* aLimited */);
477 }
478
479 /**
480 * Smart class that automatically increases the number of callers of the
481 * given VirtualBoxBase object when an instance is constructed and decreases
482 * it back when the created instance goes out of scope (i.e. gets destroyed).
483 *
484 * If #rc() returns a failure after the instance creation, it means that
485 * the managed VirtualBoxBase object is not Ready, or in any other invalid
486 * state, so that the caller must not use the object and can return this
487 * failed result code to the upper level.
488 *
489 * See VirtualBoxBase::addCaller(), VirtualBoxBase::addLimitedCaller() and
490 * VirtualBoxBase::releaseCaller() for more details about object callers.
491 *
492 * @param aLimited |false| if this template should use
493 * VirtualiBoxBase::addCaller() calls to add callers, or
494 * |true| if VirtualiBoxBase::addLimitedCaller() should be
495 * used.
496 *
497 * @note It is preferrable to use the AutoCaller and AutoLimitedCaller
498 * classes than specify the @a aLimited argument, for better
499 * self-descriptiveness.
500 */
501 template <bool aLimited>
502 class AutoCallerBase
503 {
504 public:
505
506 /**
507 * Increases the number of callers of the given object
508 * by calling VirtualBoxBase::addCaller().
509 *
510 * @param aObj Object to add a caller to. If NULL, this
511 * instance is effectively turned to no-op (where
512 * rc() will return S_OK and state() will be
513 * NotReady).
514 */
515 AutoCallerBase (VirtualBoxBaseNEXT_base *aObj)
516 : mObj (aObj)
517 , mRC (S_OK)
518 , mState (NotReady)
519 {
520 if (mObj)
521 mRC = mObj->addCaller (&mState, aLimited);
522 }
523
524 /**
525 * If the number of callers was successfully increased,
526 * decreases it using VirtualBoxBase::releaseCaller(), otherwise
527 * does nothing.
528 */
529 ~AutoCallerBase()
530 {
531 if (mObj && SUCCEEDED (mRC))
532 mObj->releaseCaller();
533 }
534
535 /**
536 * Stores the result code returned by VirtualBoxBase::addCaller()
537 * after instance creation or after the last #add() call. A successful
538 * result code means the number of callers was successfully increased.
539 */
540 HRESULT rc() const { return mRC; }
541
542 /**
543 * Returns |true| if |SUCCEEDED (rc())| is |true|, for convenience.
544 * |true| means the number of callers was successfully increased.
545 */
546 bool isOk() const { return SUCCEEDED (mRC); }
547
548 /**
549 * Stores the object state returned by VirtualBoxBase::addCaller()
550 * after instance creation or after the last #add() call.
551 */
552 State state() const { return mState; }
553
554 /**
555 * Temporarily decreases the number of callers of the managed object.
556 * May only be called if #isOk() returns |true|. Note that #rc() will
557 * return E_FAIL after this method succeeds.
558 */
559 void release()
560 {
561 Assert (SUCCEEDED (mRC));
562 if (SUCCEEDED (mRC))
563 {
564 if (mObj)
565 mObj->releaseCaller();
566 mRC = E_FAIL;
567 }
568 }
569
570 /**
571 * Restores the number of callers decreased by #release(). May only
572 * be called after #release().
573 */
574 void add()
575 {
576 Assert (!SUCCEEDED (mRC));
577 if (mObj && !SUCCEEDED (mRC))
578 mRC = mObj->addCaller (&mState, aLimited);
579 }
580
581 private:
582
583 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (AutoCallerBase)
584 DECLARE_CLS_NEW_DELETE_NOOP (AutoCallerBase)
585
586 VirtualBoxBaseNEXT_base *mObj;
587 HRESULT mRC;
588 State mState;
589 };
590
591 /**
592 * Smart class that automatically increases the number of normal
593 * (non-limited) callers of the given VirtualBoxBase object when an
594 * instance is constructed and decreases it back when the created instance
595 * goes out of scope (i.e. gets destroyed).
596 *
597 * A typical usage pattern to declare a normal method of some object
598 * (i.e. a method that is valid only when the object provides its
599 * full functionality) is:
600 * <code>
601 * STDMETHODIMP Component::Foo()
602 * {
603 * AutoCaller autoCaller (this);
604 * CheckComRCReturnRC (autoCaller.rc());
605 * ...
606 * </code>
607 *
608 * Using this class is equivalent to using the AutoCallerBase template
609 * with the @a aLimited argument set to |false|, but this class is
610 * preferred because provides better self-descriptiveness.
611 *
612 * See AutoCallerBase for more information about auto caller functionality.
613 */
614 typedef AutoCallerBase <false> AutoCaller;
615
616 /**
617 * Smart class that automatically increases the number of limited callers
618 * of the given VirtualBoxBase object when an instance is constructed and
619 * decreases it back when the created instance goes out of scope (i.e.
620 * gets destroyed).
621 *
622 * A typical usage pattern to declare a limited method of some object
623 * (i.e. a method that is valid even if the object doesn't provide its
624 * full functionality) is:
625 * <code>
626 * STDMETHODIMP Component::Bar()
627 * {
628 * AutoLimitedCaller autoCaller (this);
629 * CheckComRCReturnRC (autoCaller.rc());
630 * ...
631 * </code>
632 *
633 * Using this class is equivalent to using the AutoCallerBase template
634 * with the @a aLimited argument set to |true|, but this class is
635 * preferred because provides better self-descriptiveness.
636 *
637 * See AutoCallerBase for more information about auto caller functionality.
638 */
639 typedef AutoCallerBase <true> AutoLimitedCaller;
640
641protected:
642
643 /**
644 * Smart class to enclose the state transition NotReady->InInit->Ready.
645 *
646 * Instances must be created at the beginning of init() methods of
647 * VirtualBoxBase subclasses as a stack-based variable using |this| pointer
648 * as the argument. When this variable is created it automatically places
649 * the object to the InInit state.
650 *
651 * When the created variable goes out of scope (i.e. gets destroyed),
652 * depending on the success status of this initialization span, it either
653 * places the object to the Ready state or calls the object's
654 * VirtualBoxBase::uninit() method which is supposed to place the object
655 * back to the NotReady state using the AutoUninitSpan class.
656 *
657 * The initial success status of the initialization span is determined by
658 * the @a aSuccess argument of the AutoInitSpan constructor (|false| by
659 * default). Inside the initialization span, the success status can be set
660 * to |true| using #setSucceeded() or to |false| using #setFailed(). Please
661 * don't forget to set the correct success status before letting the
662 * AutoInitSpan variable go out of scope (for example, by performing an
663 * early return from the init() method)!
664 *
665 * Note that if an instance of this class gets constructed when the
666 * object is in the state other than NotReady, #isOk() returns |false| and
667 * methods of this class do nothing: the state transition is not performed.
668 *
669 * A typical usage pattern is:
670 * <code>
671 * HRESULT Component::init()
672 * {
673 * AutoInitSpan autoInitSpan (this);
674 * AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
675 * ...
676 * if (FAILED (rc))
677 * return rc;
678 * ...
679 * if (SUCCEEDED (rc))
680 * autoInitSpan.setSucceeded();
681 * return rc;
682 * }
683 * </code>
684 *
685 * @note Never create instances of this class outside init() methods of
686 * VirtualBoxBase subclasses and never pass anything other than |this| as
687 * the argument to the constructor!
688 */
689 class AutoInitSpan
690 {
691 public:
692
693 enum Status { Failed = 0x0, Succeeded = 0x1, Limited = 0x2 };
694
695 AutoInitSpan (VirtualBoxBaseNEXT_base *aObj, Status aStatus = Failed);
696 ~AutoInitSpan();
697
698 /**
699 * Returns |true| if this instance has been created at the right moment
700 * (when the object was in the NotReady state) and |false| otherwise.
701 */
702 bool isOk() const { return mOk; }
703
704 /**
705 * Sets the initialization status to Succeeded to indicates successful
706 * initialization. The AutoInitSpan destructor will place the managed
707 * VirtualBoxBase object to the Ready state.
708 */
709 void setSucceeded() { mStatus = Succeeded; }
710
711 /**
712 * Sets the initialization status to Succeeded to indicate limited
713 * (partly successful) initialization. The AutoInitSpan destructor will
714 * place the managed VirtualBoxBase object to the Limited state.
715 */
716 void setLimited() { mStatus = Limited; }
717
718 /**
719 * Sets the initialization status to Failure to indicates failed
720 * initialization. The AutoInitSpan destructor will place the managed
721 * VirtualBoxBase object to the InitFailed state and will automatically
722 * call its uninit() method which is supposed to place the object back
723 * to the NotReady state using AutoUninitSpan.
724 */
725 void setFailed() { mStatus = Failed; }
726
727 /** Returns the current initialization status. */
728 Status status() { return mStatus; }
729
730 private:
731
732 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (AutoInitSpan)
733 DECLARE_CLS_NEW_DELETE_NOOP (AutoInitSpan)
734
735 VirtualBoxBaseNEXT_base *mObj;
736 Status mStatus : 3; // must be at least total number of bits + 1 (sign)
737 bool mOk : 1;
738 };
739
740 /**
741 * Smart class to enclose the state transition Limited->InInit->Ready.
742 *
743 * Instances must be created at the beginning of methods of VirtualBoxBase
744 * subclasses that try to re-initialize the object to bring it to the
745 * Ready state (full functionality) after partial initialization
746 * (limited functionality)>, as a stack-based variable using |this| pointer
747 * as the argument. When this variable is created it automatically places
748 * the object to the InInit state.
749 *
750 * When the created variable goes out of scope (i.e. gets destroyed),
751 * depending on the success status of this initialization span, it either
752 * places the object to the Ready state or brings it back to the Limited
753 * state.
754 *
755 * The initial success status of the re-initialization span is |false|.
756 * In order to make it successful, #setSucceeded() must be called before
757 * the instance is destroyed.
758 *
759 * Note that if an instance of this class gets constructed when the
760 * object is in the state other than Limited, #isOk() returns |false| and
761 * methods of this class do nothing: the state transition is not performed.
762 *
763 * A typical usage pattern is:
764 * <code>
765 * HRESULT Component::reinit()
766 * {
767 * AutoReadySpan autoReadySpan (this);
768 * AssertReturn (autoReadySpan.isOk(), E_UNEXPECTED);
769 * ...
770 * if (FAILED (rc))
771 * return rc;
772 * ...
773 * if (SUCCEEDED (rc))
774 * autoReadySpan.setSucceeded();
775 * return rc;
776 * }
777 * </code>
778 *
779 * @note Never create instances of this class outside re-initialization
780 * methods of VirtualBoxBase subclasses and never pass anything other than
781 * |this| as the argument to the constructor!
782 */
783 class AutoReadySpan
784 {
785 public:
786
787 AutoReadySpan (VirtualBoxBaseNEXT_base *aObj);
788 ~AutoReadySpan();
789
790 /**
791 * Returns |true| if this instance has been created at the right moment
792 * (when the object was in the Limited state) and |false| otherwise.
793 */
794 bool isOk() const { return mOk; }
795
796 /**
797 * Sets the re-initialization status to Succeeded to indicates
798 * successful re-initialization. The AutoReadySpan destructor will
799 * place the managed VirtualBoxBase object to the Ready state.
800 */
801 void setSucceeded() { mSucceeded = true; }
802
803 private:
804
805 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (AutoReadySpan)
806 DECLARE_CLS_NEW_DELETE_NOOP (AutoReadySpan)
807
808 VirtualBoxBaseNEXT_base *mObj;
809 bool mSucceeded : 1;
810 bool mOk : 1;
811 };
812
813 /**
814 * Smart class to enclose the state transition Ready->InUnnit->NotReady or
815 * InitFailed->InUnnit->NotReady.
816 *
817 * Must be created at the beginning of uninit() methods of VirtualBoxBase
818 * subclasses as a stack-based variable using |this| pointer as the argument.
819 * When this variable is created it automatically places the object to the
820 * InUninit state, unless it is already in the NotReady state as indicated
821 * by #uninitDone() returning |true|. In the latter case, the uninit()
822 * method must immediately return because there should be nothing to
823 * uninitialize.
824 *
825 * When this variable goes out of scope (i.e. gets destroyed), it places
826 * the object to the NotReady state.
827 *
828 * A typical usage pattern is:
829 * <code>
830 * void Component::uninit()
831 * {
832 * AutoUninitSpan autoUninitSpan (this);
833 * if (autoUninitSpan.uninitDone())
834 * retrun;
835 * ...
836 * </code>
837 *
838 * @note Never create instances of this class outside uninit() methods and
839 * never pass anything other than |this| as the argument to the constructor!
840 */
841 class AutoUninitSpan
842 {
843 public:
844
845 AutoUninitSpan (VirtualBoxBaseNEXT_base *aObj);
846 ~AutoUninitSpan();
847
848 /** |true| when uninit() is called as a result of init() failure */
849 bool initFailed() { return mInitFailed; }
850
851 /** |true| when uninit() has already been called (so the object is NotReady) */
852 bool uninitDone() { return mUninitDone; }
853
854 private:
855
856 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (AutoUninitSpan)
857 DECLARE_CLS_NEW_DELETE_NOOP (AutoUninitSpan)
858
859 VirtualBoxBaseNEXT_base *mObj;
860 bool mInitFailed : 1;
861 bool mUninitDone : 1;
862 };
863
864private:
865
866 void setState (State aState)
867 {
868 Assert (mState != aState);
869 mState = aState;
870 mStateChangeThread = RTThreadSelf();
871 }
872
873 /** Primary state of this object */
874 State mState;
875 /** Thread that caused the last state change */
876 RTTHREAD mStateChangeThread;
877 /** Total number of active calls to this object */
878 unsigned mCallers;
879 /** Semaphore posted when the number of callers drops to zero */
880 RTSEMEVENT mZeroCallersSem;
881 /** Semaphore posted when the object goes from InInit some other state */
882 RTSEMEVENTMULTI mInitDoneSem;
883 /** Number of threads waiting for mInitDoneSem */
884 unsigned mInitDoneSemUsers;
885
886 /** Protects access to state related data members */
887 RTCRITSECT mStateLock;
888
889 /** User-level object lock for subclasses */
890 mutable AutoLock::Handle *mObjectLock;
891};
892
893/**
894 * This macro adds the error info support to methods of the VirtualBoxBase
895 * class (by overriding them). Place it to the public section of the
896 * VirtualBoxBase subclass and the following methods will set the extended
897 * error info in case of failure instead of just returning the result code:
898 *
899 * <ul>
900 * <li>VirtualBoxBase::addCaller()
901 * </ul>
902 *
903 * @note The given VirtualBoxBase subclass must also inherit from both
904 * VirtualBoxSupportErrorInfoImpl and VirtualBoxSupportTranslation templates!
905 *
906 * @param C VirtualBoxBase subclass to add the error info support to
907 */
908#define VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(C) \
909 virtual HRESULT addCaller (VirtualBoxBaseNEXT_base::State *aState = NULL, \
910 bool aLimited = false) \
911 { \
912 VirtualBoxBaseNEXT_base::State state; \
913 HRESULT rc = VirtualBoxBaseNEXT_base::addCaller (&state, aLimited); \
914 if (FAILED (rc)) \
915 { \
916 if (state == VirtualBoxBaseNEXT_base::Limited) \
917 rc = setError (rc, tr ("The object functonality is limited")); \
918 else \
919 rc = setError (rc, tr ("The object is not ready")); \
920 } \
921 if (aState) \
922 *aState = state; \
923 return rc; \
924 } \
925
926////////////////////////////////////////////////////////////////////////////////
927
928/// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
929class ATL_NO_VTABLE VirtualBoxBase : public VirtualBoxBaseNEXT_base
930//#ifdef RT_OS_WINDOWS
931// : public CComObjectRootEx<CComMultiThreadModel>
932//#else
933// : public CComObjectRootEx
934//#endif
935{
936
937public:
938 VirtualBoxBase()
939 {
940 mReady = false;
941 }
942 virtual ~VirtualBoxBase()
943 {
944 }
945
946 /**
947 * Virtual unintialization method. Called during parent object's
948 * uninitialization, if the given subclass instance is a dependent child of
949 * a class dervived from VirtualBoxBaseWithChildren (@sa
950 * VirtualBoxBaseWithChildren::addDependentChild). In this case, this
951 * method's impelemtation must call setReady (false),
952 */
953 virtual void uninit() {}
954
955
956 // sets the ready state of the object
957 void setReady(bool isReady)
958 {
959 mReady = isReady;
960 }
961 // get the ready state of the object
962 bool isReady()
963 {
964 return mReady;
965 }
966
967 static const char *translate (const char *context, const char *sourceText,
968 const char *comment = 0);
969
970private:
971
972 // flag determining whether an object is ready
973 // for usage, i.e. methods may be called
974 bool mReady;
975 // mutex semaphore to lock the object
976};
977
978/**
979 * Temporary class to disable deprecated methods of VirtualBoxBase.
980 * Can be used as a base for components that are completely switched to
981 * the new locking scheme (VirtualBoxBaseNEXT_base).
982 *
983 * @todo remove after we switch to VirtualBoxBaseNEXT completely.
984 */
985class VirtualBoxBaseNEXT : public VirtualBoxBase
986{
987private:
988
989 void lock();
990 void unlock();
991 void setReady (bool isReady);
992 bool isReady();
993};
994
995////////////////////////////////////////////////////////////////////////////////
996
997/** Helper for VirtualBoxSupportTranslation */
998class VirtualBoxSupportTranslationBase
999{
1000protected:
1001 static bool cutClassNameFrom__PRETTY_FUNCTION__ (char *prettyFunctionName);
1002};
1003
1004/**
1005 * This template implements the NLS string translation support for the
1006 * given class by providing a #tr() function.
1007 *
1008 * @param C class that needs to support the string translation
1009 *
1010 * @note
1011 * Every class that wants to use the #tr() function in its own methods must
1012 * inherit from this template, regardless of whether its base class (if any)
1013 * inherits from it or not! Otherwise, the translation service will not
1014 * work correctly. However, the declaration of the resulting class must
1015 * contain the VIRTUALBOXSUPPORTTRANSLATION_OVERRIDE(<ClassName>) macro
1016 * if one of its base classes also inherits from this template (to resolve
1017 * the ambiguity of the #tr() function).
1018 */
1019template <class C>
1020class VirtualBoxSupportTranslation : virtual protected VirtualBoxSupportTranslationBase
1021{
1022public:
1023
1024 /**
1025 * Translates the given text string according to the currently installed
1026 * translation table and current context, which is determined by the
1027 * class name. See VirtualBoxBase::translate() for more info.
1028 *
1029 * @param sourceText the string to translate
1030 * @param comment the comment to the string (NULL means no comment)
1031 *
1032 * @return
1033 * the translated version of the source string in UTF-8 encoding,
1034 * or the source string itself if the translation is not found in
1035 * the current context.
1036 */
1037 inline static const char *tr (const char *sourceText, const char *comment = 0)
1038 {
1039 return VirtualBoxBase::translate (getClassName(), sourceText, comment);
1040 }
1041
1042protected:
1043
1044 static const char *getClassName()
1045 {
1046 static char fn [sizeof (__PRETTY_FUNCTION__) + 1];
1047 if (!className)
1048 {
1049 strcpy (fn, __PRETTY_FUNCTION__);
1050 cutClassNameFrom__PRETTY_FUNCTION__ (fn);
1051 className = fn;
1052 }
1053 return className;
1054 }
1055
1056private:
1057
1058 static const char *className;
1059};
1060
1061template <class C>
1062const char *VirtualBoxSupportTranslation <C>::className = NULL;
1063
1064/**
1065 * This macro must be invoked inside the public section of the declaration of
1066 * the class inherited from the VirtualBoxSupportTranslation template, in case
1067 * when one of its other base classes also inherits from that template. This is
1068 * necessary to resolve the ambiguity of the #tr() function.
1069 *
1070 * @param C class that inherits from the VirtualBoxSupportTranslation template
1071 * more than once (through its other base clases)
1072 */
1073#define VIRTUALBOXSUPPORTTRANSLATION_OVERRIDE(C) \
1074 inline static const char *tr (const char *sourceText, const char *comment = 0) \
1075 { \
1076 return VirtualBoxSupportTranslation <C>::tr (sourceText, comment); \
1077 }
1078
1079/**
1080 * A dummy macro that is used to shut down Qt's lupdate tool warnings
1081 * in some situations. This macro needs to be present inside (better at the
1082 * very beginning) of the declaration of the class that inherits from
1083 * VirtualBoxSupportTranslation template, to make lupdate happy.
1084 */
1085#define Q_OBJECT
1086
1087////////////////////////////////////////////////////////////////////////////////
1088
1089/**
1090 * Helper for the VirtualBoxSupportErrorInfoImpl template.
1091 */
1092class VirtualBoxSupportErrorInfoImplBase
1093{
1094 static HRESULT setErrorInternal (HRESULT aResultCode, const GUID &aIID,
1095 const Bstr &aComponent, const Bstr &aText,
1096 bool aPreserve);
1097
1098protected:
1099
1100 inline static HRESULT setError (HRESULT aResultCode, const GUID &aIID,
1101 const Bstr &aComponent,
1102 const Bstr &aText)
1103 {
1104 return setErrorInternal (aResultCode, aIID, aComponent, aText,
1105 false /* aPreserve */);
1106 }
1107
1108 inline static HRESULT addError (HRESULT aResultCode, const GUID &aIID,
1109 const Bstr &aComponent,
1110 const Bstr &aText)
1111 {
1112 return setErrorInternal (aResultCode, aIID, aComponent, aText,
1113 true /* aPreserve */);
1114 }
1115
1116 static HRESULT setError (HRESULT aResultCode, const GUID &aIID,
1117 const Bstr &aComponent,
1118 const char *aText, va_list aArgs)
1119 {
1120 return setErrorInternal (aResultCode, aIID, aComponent,
1121 Utf8StrFmtVA (aText, aArgs),
1122 false /* aPreserve */);
1123 }
1124
1125 static HRESULT addError (HRESULT aResultCode, const GUID &aIID,
1126 const Bstr &aComponent,
1127 const char *aText, va_list aArgs)
1128 {
1129 return setErrorInternal (aResultCode, aIID, aComponent,
1130 Utf8StrFmtVA (aText, aArgs),
1131 true /* aPreserve */);
1132 }
1133};
1134
1135/**
1136 * This template implements ISupportErrorInfo for the given component class
1137 * and provides the #setError() method to conveniently set the error information
1138 * from within interface methods' implementations.
1139 *
1140 * On Windows, the template argument must define a COM interface map using
1141 * BEGIN_COM_MAP / END_COM_MAP macros and this map must contain a
1142 * COM_INTERFACE_ENTRY(ISupportErrorInfo) definition. All interface entries
1143 * that follow it will be considered to support IErrorInfo, i.e. the
1144 * InterfaceSupportsErrorInfo() implementation will return S_OK for the
1145 * corresponding IID.
1146 *
1147 * On all platforms, the template argument must also define the following
1148 * method: |public static const wchar_t *C::getComponentName()|. See
1149 * #setError (HRESULT, const char *, ...) for a description on how it is
1150 * used.
1151 *
1152 * @param C
1153 * component class that implements one or more COM interfaces
1154 * @param I
1155 * default interface for the component. This interface's IID is used
1156 * by the shortest form of #setError, for convenience.
1157 */
1158template <class C, class I>
1159class ATL_NO_VTABLE VirtualBoxSupportErrorInfoImpl
1160 : protected VirtualBoxSupportErrorInfoImplBase
1161#if defined (RT_OS_WINDOWS)
1162 , public ISupportErrorInfo
1163#else
1164#endif
1165{
1166public:
1167
1168#if defined (RT_OS_WINDOWS)
1169 STDMETHOD(InterfaceSupportsErrorInfo) (REFIID riid)
1170 {
1171 const _ATL_INTMAP_ENTRY* pEntries = C::_GetEntries();
1172 Assert (pEntries);
1173 if (!pEntries)
1174 return S_FALSE;
1175
1176 BOOL bSupports = FALSE;
1177 BOOL bISupportErrorInfoFound = FALSE;
1178
1179 while (pEntries->pFunc != NULL && !bSupports)
1180 {
1181 if (!bISupportErrorInfoFound)
1182 {
1183 // skip the com map entries until ISupportErrorInfo is found
1184 bISupportErrorInfoFound =
1185 InlineIsEqualGUID (*(pEntries->piid), IID_ISupportErrorInfo);
1186 }
1187 else
1188 {
1189 // look for the requested interface in the rest of the com map
1190 bSupports = InlineIsEqualGUID (*(pEntries->piid), riid);
1191 }
1192 pEntries++;
1193 }
1194
1195 Assert (bISupportErrorInfoFound);
1196
1197 return bSupports ? S_OK : S_FALSE;
1198 }
1199#endif // defined (RT_OS_WINDOWS)
1200
1201protected:
1202
1203 /**
1204 * Sets the error information for the current thread.
1205 * This information can be retrieved by a caller of an interface method
1206 * using IErrorInfo on Windows or nsIException on Linux, or the cross-platform
1207 * IVirtualBoxErrorInfo interface that provides extended error info (only
1208 * for components from the VirtualBox COM library). Alternatively, the
1209 * platform-independent class com::ErrorInfo (defined in VBox[XP]COM.lib)
1210 * can be used to retrieve error info in a convenient way.
1211 *
1212 * It is assumed that the interface method that uses this function returns
1213 * an unsuccessful result code to the caller (otherwise, there is no reason
1214 * for the caller to try to retrieve error info after method invocation).
1215 *
1216 * Here is a table of correspondence between this method's arguments
1217 * and IErrorInfo/nsIException/IVirtualBoxErrorInfo attributes/methods:
1218 *
1219 * argument IErrorInfo nsIException IVirtualBoxErrorInfo
1220 * ----------------------------------------------------------------
1221 * resultCode -- result resultCode
1222 * iid GetGUID -- interfaceID
1223 * component GetSource -- component
1224 * text GetDescription message text
1225 *
1226 * This method is rarely needs to be used though. There are more convenient
1227 * overloaded versions, that automatically substitute some arguments
1228 * taking their values from the template parameters. See
1229 * #setError (HRESULT, const char *, ...) for an example.
1230 *
1231 * @param aResultCode result (error) code, must not be S_OK
1232 * @param aIID IID of the intrface that defines the error
1233 * @param aComponent name of the component that generates the error
1234 * @param aText error message (must not be null), an RTStrPrintf-like
1235 * format string in UTF-8 encoding
1236 * @param ... list of arguments for the format string
1237 *
1238 * @return
1239 * the error argument, for convenience, If an error occures while
1240 * creating error info itself, that error is returned instead of the
1241 * error argument.
1242 */
1243 inline static HRESULT setError (HRESULT aResultCode, const GUID &aIID,
1244 const wchar_t *aComponent,
1245 const char *aText, ...)
1246 {
1247 va_list args;
1248 va_start (args, aText);
1249 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError
1250 (aResultCode, aIID, aComponent, aText, args);
1251 va_end (args);
1252 return rc;
1253 }
1254
1255 /**
1256 * This method is the same as #setError() except that it preserves the
1257 * error info object (if any) set for the current thread before this
1258 * method is called by storing it in the IVirtualBoxErrorInfo::next
1259 * attribute of the new error info object.
1260 */
1261 inline static HRESULT addError (HRESULT aResultCode, const GUID &aIID,
1262 const wchar_t *aComponent,
1263 const char *aText, ...)
1264 {
1265 va_list args;
1266 va_start (args, aText);
1267 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::addError
1268 (aResultCode, aIID, aComponent, aText, args);
1269 va_end (args);
1270 return rc;
1271 }
1272
1273 /**
1274 * Sets the error information for the current thread.
1275 * A convenience method that automatically sets the default interface
1276 * ID (taken from the I template argument) and the component name
1277 * (a value of C::getComponentName()).
1278 *
1279 * See #setError (HRESULT, const GUID &, const wchar_t *, const char *text, ...)
1280 * for details.
1281 *
1282 * This method is the most common (and convenient) way to set error
1283 * information from within interface methods. A typical pattern of usage
1284 * is looks like this:
1285 *
1286 * <code>
1287 * return setError (E_FAIL, "Terrible Error");
1288 * </code>
1289 * or
1290 * <code>
1291 * HRESULT rc = setError (E_FAIL, "Terrible Error");
1292 * ...
1293 * return rc;
1294 * </code>
1295 */
1296 inline static HRESULT setError (HRESULT aResultCode, const char *aText, ...)
1297 {
1298 va_list args;
1299 va_start (args, aText);
1300 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError
1301 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText, args);
1302 va_end (args);
1303 return rc;
1304 }
1305
1306 /**
1307 * This method is the same as #setError() except that it preserves the
1308 * error info object (if any) set for the current thread before this
1309 * method is called by storing it in the IVirtualBoxErrorInfo::next
1310 * attribute of the new error info object.
1311 */
1312 inline static HRESULT addError (HRESULT aResultCode, const char *aText, ...)
1313 {
1314 va_list args;
1315 va_start (args, aText);
1316 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::addError
1317 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText, args);
1318 va_end (args);
1319 return rc;
1320 }
1321
1322 /**
1323 * Sets the error information for the current thread, va_list variant.
1324 * A convenience method that automatically sets the default interface
1325 * ID (taken from the I template argument) and the component name
1326 * (a value of C::getComponentName()).
1327 *
1328 * See #setError (HRESULT, const GUID &, const wchar_t *, const char *text, ...)
1329 * and #setError (HRESULT, const char *, ...) for details.
1330 */
1331 inline static HRESULT setErrorV (HRESULT aResultCode, const char *aText,
1332 va_list aArgs)
1333 {
1334 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError
1335 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText, aArgs);
1336 return rc;
1337 }
1338
1339 /**
1340 * This method is the same as #setErrorV() except that it preserves the
1341 * error info object (if any) set for the current thread before this
1342 * method is called by storing it in the IVirtualBoxErrorInfo::next
1343 * attribute of the new error info object.
1344 */
1345 inline static HRESULT addErrorV (HRESULT aResultCode, const char *aText,
1346 va_list aArgs)
1347 {
1348 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::addError
1349 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText, aArgs);
1350 return rc;
1351 }
1352
1353 /**
1354 * Sets the error information for the current thread, BStr variant.
1355 * A convenience method that automatically sets the default interface
1356 * ID (taken from the I template argument) and the component name
1357 * (a value of C::getComponentName()).
1358 *
1359 * This method is preferred iy you have a ready (translated and formatted)
1360 * Bstr string, because it omits an extra conversion Utf8Str -> Bstr.
1361 *
1362 * See #setError (HRESULT, const GUID &, const wchar_t *, const char *text, ...)
1363 * and #setError (HRESULT, const char *, ...) for details.
1364 */
1365 inline static HRESULT setErrorBstr (HRESULT aResultCode, const Bstr &aText)
1366 {
1367 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError
1368 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText);
1369 return rc;
1370 }
1371
1372 /**
1373 * This method is the same as #setErrorBstr() except that it preserves the
1374 * error info object (if any) set for the current thread before this
1375 * method is called by storing it in the IVirtualBoxErrorInfo::next
1376 * attribute of the new error info object.
1377 */
1378 inline static HRESULT addErrorBstr (HRESULT aResultCode, const Bstr &aText)
1379 {
1380 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::addError
1381 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText);
1382 return rc;
1383 }
1384
1385 /**
1386 * Sets the error information for the current thread.
1387 * A convenience method that automatically sets the component name
1388 * (a value of C::getComponentName()), but allows to specify the interface
1389 * id manually.
1390 *
1391 * See #setError (HRESULT, const GUID &, const wchar_t *, const char *text, ...)
1392 * for details.
1393 */
1394 inline static HRESULT setError (HRESULT aResultCode, const GUID &aIID,
1395 const char *aText, ...)
1396 {
1397 va_list args;
1398 va_start (args, aText);
1399 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError
1400 (aResultCode, aIID, C::getComponentName(), aText, args);
1401 va_end (args);
1402 return rc;
1403 }
1404
1405 /**
1406 * This method is the same as #setError() except that it preserves the
1407 * error info object (if any) set for the current thread before this
1408 * method is called by storing it in the IVirtualBoxErrorInfo::next
1409 * attribute of the new error info object.
1410 */
1411 inline static HRESULT addError (HRESULT aResultCode, const GUID &aIID,
1412 const char *aText, ...)
1413 {
1414 va_list args;
1415 va_start (args, aText);
1416 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::addError
1417 (aResultCode, aIID, C::getComponentName(), aText, args);
1418 va_end (args);
1419 return rc;
1420 }
1421
1422private:
1423
1424};
1425
1426////////////////////////////////////////////////////////////////////////////////
1427
1428/**
1429 * Base class to track VirtualBoxBase chlidren of the component.
1430 *
1431 * This class is a preferrable VirtualBoxBase replacement for components
1432 * that operate with collections of child components. It gives two useful
1433 * possibilities:
1434 *
1435 * <ol><li>
1436 * Given an IUnknown instance, it's possible to quickly determine
1437 * whether this instance represents a child object created by the given
1438 * component, and if so, get a valid VirtualBoxBase pointer to the child
1439 * object. The returned pointer can be then safely casted to the
1440 * actual class of the child object (to get access to its "internal"
1441 * non-interface methods) provided that no other child components implement
1442 * the same initial interface IUnknown is queried from.
1443 * </li><li>
1444 * When the parent object uninitializes itself, it can easily unintialize
1445 * all its VirtualBoxBase derived children (using their
1446 * VirtualBoxBase::uninit() implementations). This is done simply by
1447 * calling the #uninitDependentChildren() method.
1448 * </li><ol>
1449 *
1450 * In order to let the above work, the following must be done:
1451 * <ol><li>
1452 * When a child object is initialized, it calls #addDependentChild() of
1453 * its parent to register itself within the list of dependent children.
1454 * </li><li>
1455 * When a child object it is uninitialized, it calls #removeDependentChild()
1456 * to unregister itself. This must be done <b>after</b> the child has called
1457 * setReady(false) to indicate it is no more valid, and <b>not</b> from under
1458 * the child object's lock. Note also, that the first action the child's
1459 * uninit() implementation must do is to check for readiness after acquiring
1460 * the object's lock and return immediately if not ready.
1461 * </li><ol>
1462 *
1463 * Children added by #addDependentChild() are <b>weakly</b> referenced
1464 * (i.e. AddRef() is not called), so when a child is externally destructed
1465 * (i.e. its reference count goes to zero), it will automatically remove
1466 * itself from a map of dependent children, provided that it follows the
1467 * rules described here.
1468 *
1469 * @note
1470 * Because of weak referencing, deadlocks and assertions are very likely
1471 * if #addDependentChild() or #removeDependentChild() are used incorrectly
1472 * (called at inappropriate times). Check the above rules once more.
1473 */
1474class VirtualBoxBaseWithChildren : public VirtualBoxBase
1475{
1476public:
1477
1478 VirtualBoxBaseWithChildren()
1479 : mUninitDoneSem (NIL_RTSEMEVENT), mChildrenLeft (0)
1480 {
1481 RTCritSectInit (&mMapLock);
1482 }
1483
1484 virtual ~VirtualBoxBaseWithChildren()
1485 {
1486 RTCritSectDelete (&mMapLock);
1487 }
1488
1489 /**
1490 * Adds the given child to the map of dependent children.
1491 * Intended to be called from the child's init() method,
1492 * from under the child's lock.
1493 *
1494 * @param C the child object to add (must inherit VirtualBoxBase AND
1495 * implement some interface)
1496 */
1497 template <class C>
1498 void addDependentChild (C *child)
1499 {
1500 AssertReturn (child, (void) 0);
1501 addDependentChild (child, child);
1502 }
1503
1504 /**
1505 * Removes the given child from the map of dependent children.
1506 * Must be called <b>after<b> the child has called setReady(false), and
1507 * <b>not</b> from under the child object's lock.
1508 *
1509 * @param C the child object to remove (must inherit VirtualBoxBase AND
1510 * implement some interface)
1511 */
1512 template <class C>
1513 void removeDependentChild (C *child)
1514 {
1515 AssertReturn (child, (void) 0);
1516 /// @todo (r=dmik) the below check (and the relevant comment above)
1517 // seems to be not necessary any more once we completely switch to
1518 // the NEXT locking scheme. This requires altering removeDependentChild()
1519 // and uninitDependentChildren() as well (due to the new state scheme,
1520 // there is a separate mutex for state transition, so calling the
1521 // child's uninit() from under the children map lock should not produce
1522 // dead-locks any more).
1523 Assert (!child->isLockedOnCurrentThread());
1524 removeDependentChild (ComPtr <IUnknown> (child));
1525 }
1526
1527protected:
1528
1529 void uninitDependentChildren();
1530
1531 VirtualBoxBase *getDependentChild (const ComPtr <IUnknown> &unk);
1532
1533private:
1534
1535 void addDependentChild (const ComPtr <IUnknown> &unk, VirtualBoxBase *child);
1536 void removeDependentChild (const ComPtr <IUnknown> &unk);
1537
1538 typedef std::map <IUnknown *, VirtualBoxBase *> DependentChildren;
1539 DependentChildren mDependentChildren;
1540
1541 RTCRITSECT mMapLock;
1542 RTSEMEVENT mUninitDoneSem;
1543 unsigned mChildrenLeft;
1544};
1545
1546/**
1547 * Temporary class to disable deprecated methods of VirtualBoxBase.
1548 * Can be used as a base for components that are completely switched to
1549 * the new locking scheme (VirtualBoxBaseNEXT_base).
1550 *
1551 * @todo remove after we switch to VirtualBoxBaseNEXT completely.
1552 */
1553class VirtualBoxBaseWithChildrenNEXT : public VirtualBoxBaseWithChildren
1554{
1555private:
1556
1557 void lock();
1558 void unlock();
1559 void setReady (bool isReady);
1560 bool isReady();
1561};
1562
1563////////////////////////////////////////////////////////////////////////////////
1564
1565/**
1566 * Base class to track component's chlidren of some particular type.
1567 *
1568 * This class is similar to VirtualBoxBaseWithChildren, with the exception
1569 * that all children must be of the same type. For this reason, it's not
1570 * necessary to use a map to store children, so a list is used instead.
1571 *
1572 * As opposed to VirtualBoxBaseWithChildren, children added by
1573 * #addDependentChild() are <b>strongly</b> referenced, so that they cannot
1574 * be externally destructed until #removeDependentChild() is called.
1575 * For this reason, strict rules of calling #removeDependentChild() don't
1576 * apply to instances of this class -- it can be called anywhere in the
1577 * child's uninit() implementation.
1578 *
1579 * @param C type of child objects (must inherit VirtualBoxBase AND
1580 * implement some interface)
1581 */
1582template <class C>
1583class VirtualBoxBaseWithTypedChildren : public VirtualBoxBase
1584{
1585public:
1586
1587 typedef std::list <ComObjPtr <C> > DependentChildren;
1588
1589 VirtualBoxBaseWithTypedChildren() : mInUninit (false) {}
1590
1591 virtual ~VirtualBoxBaseWithTypedChildren() {}
1592
1593 /**
1594 * Adds the given child to the list of dependent children.
1595 * Must be called from the child's init() method,
1596 * from under the child's lock.
1597 *
1598 * @param C the child object to add (must inherit VirtualBoxBase AND
1599 * implement some interface)
1600 */
1601 void addDependentChild (C *child)
1602 {
1603 AssertReturn (child, (void) 0);
1604
1605 AutoLock alock (mMapLock);
1606 if (mInUninit)
1607 return;
1608
1609 mDependentChildren.push_back (child);
1610 }
1611
1612 /**
1613 * Removes the given child from the list of dependent children.
1614 * Must be called from the child's uninit() method,
1615 * under the child's lock.
1616 *
1617 * @param C the child object to remove (must inherit VirtualBoxBase AND
1618 * implement some interface)
1619 */
1620 void removeDependentChild (C *child)
1621 {
1622 AssertReturn (child, (void) 0);
1623
1624 AutoLock alock (mMapLock);
1625 if (mInUninit)
1626 return;
1627
1628 mDependentChildren.remove (child);
1629 }
1630
1631protected:
1632
1633 /**
1634 * Returns an internal lock handle to lock the list of children
1635 * returned by #dependentChildren() using AutoLock:
1636 * <code>
1637 * AutoLock alock (dependentChildrenLock());
1638 * </code>
1639 */
1640 AutoLock::Handle &dependentChildrenLock() const { return mMapLock; }
1641
1642 /**
1643 * Returns the read-only list of all dependent children.
1644 * @note
1645 * Access the returned list (iterate, get size etc.) only after
1646 * doing |AutoLock alock (dependentChildrenLock());|!
1647 */
1648 const DependentChildren &dependentChildren() const { return mDependentChildren; }
1649
1650 /**
1651 * Uninitializes all dependent children registered with #addDependentChild().
1652 *
1653 * @note
1654 * This method will call uninit() methods of children. If these methods
1655 * access the parent object, uninitDependentChildren() must be called
1656 * either at the beginning of the parent uninitialization sequence (when
1657 * it is still operational) or after setReady(false) is called to
1658 * indicate the parent is out of action.
1659 */
1660 void uninitDependentChildren()
1661 {
1662 AutoLock alock (this);
1663 AutoLock mapLock (mMapLock);
1664
1665 if (mDependentChildren.size())
1666 {
1667 // set flag to ignore #removeDependentChild() called from child->uninit()
1668 mInUninit = true;
1669
1670 // leave the locks to let children waiting for #removeDependentChild() run
1671 mapLock.leave();
1672 alock.leave();
1673
1674 for (typename DependentChildren::iterator it = mDependentChildren.begin();
1675 it != mDependentChildren.end(); ++ it)
1676 {
1677 C *child = (*it);
1678 Assert (child);
1679 if (child)
1680 child->uninit();
1681 }
1682 mDependentChildren.clear();
1683
1684 alock.enter();
1685 mapLock.enter();
1686
1687 mInUninit = false;
1688 }
1689 }
1690
1691 /**
1692 * Removes (detaches) all dependent children registered with
1693 * #addDependentChild(), without uninitializing them.
1694 *
1695 * @note This method must be called from under the main object's lock
1696 */
1697 void removeDependentChildren()
1698 {
1699 AutoLock alock (mMapLock);
1700 mDependentChildren.clear();
1701 }
1702
1703private:
1704
1705 DependentChildren mDependentChildren;
1706
1707 bool mInUninit;
1708 mutable AutoLock::Handle mMapLock;
1709};
1710
1711/**
1712 * Temporary class to disable deprecated methods of VirtualBoxBase.
1713 * Can be used as a base for components that are completely switched to
1714 * the new locking scheme (VirtualBoxBaseNEXT_base).
1715 *
1716 * @todo remove after we switch to VirtualBoxBaseNEXT completely.
1717 */
1718template <class C>
1719class VirtualBoxBaseWithTypedChildrenNEXT : public VirtualBoxBaseWithTypedChildren <C>
1720{
1721public:
1722
1723 typedef util::AutoLock AutoLock;
1724
1725private:
1726
1727 void lock();
1728 void unlock();
1729 bool isLockedOnCurrentThread();
1730 void setReady (bool isReady);
1731 bool isReady();
1732};
1733
1734////////////////////////////////////////////////////////////////////////////////
1735
1736/// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
1737/**
1738 * Simple template that manages data structure allocation/deallocation
1739 * and supports data pointer sharing (the instance that shares the pointer is
1740 * not responsible for memory deallocation as opposed to the instance that
1741 * owns it).
1742 */
1743template <class D>
1744class Shareable
1745{
1746public:
1747
1748 Shareable() : mData (NULL), mIsShared (FALSE) {}
1749 ~Shareable() { free(); }
1750
1751 void allocate() { attach (new D); }
1752
1753 virtual void free() {
1754 if (mData) {
1755 if (!mIsShared)
1756 delete mData;
1757 mData = NULL;
1758 mIsShared = false;
1759 }
1760 }
1761
1762 void attach (D *data) {
1763 AssertMsg (data, ("new data must not be NULL"));
1764 if (data && mData != data) {
1765 if (mData && !mIsShared)
1766 delete mData;
1767 mData = data;
1768 mIsShared = false;
1769 }
1770 }
1771
1772 void attach (Shareable &data) {
1773 AssertMsg (
1774 data.mData == mData || !data.mIsShared,
1775 ("new data must not be shared")
1776 );
1777 if (this != &data && !data.mIsShared) {
1778 attach (data.mData);
1779 data.mIsShared = true;
1780 }
1781 }
1782
1783 void share (D *data) {
1784 AssertMsg (data, ("new data must not be NULL"));
1785 if (mData != data) {
1786 if (mData && !mIsShared)
1787 delete mData;
1788 mData = data;
1789 mIsShared = true;
1790 }
1791 }
1792
1793 void share (const Shareable &data) { share (data.mData); }
1794
1795 void attachCopy (const D *data) {
1796 AssertMsg (data, ("data to copy must not be NULL"));
1797 if (data)
1798 attach (new D (*data));
1799 }
1800
1801 void attachCopy (const Shareable &data) {
1802 attachCopy (data.mData);
1803 }
1804
1805 virtual D *detach() {
1806 D *d = mData;
1807 mData = NULL;
1808 mIsShared = false;
1809 return d;
1810 }
1811
1812 D *data() const {
1813 return mData;
1814 }
1815
1816 D *operator->() const {
1817 AssertMsg (mData, ("data must not be NULL"));
1818 return mData;
1819 }
1820
1821 bool isNull() const { return mData == NULL; }
1822 bool operator!() const { return isNull(); }
1823
1824 bool isShared() const { return mIsShared; }
1825
1826protected:
1827
1828 D *mData;
1829 bool mIsShared;
1830};
1831
1832/// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
1833/**
1834 * Simple template that enhances Shareable<> and supports data
1835 * backup/rollback/commit (using the copy constructor of the managed data
1836 * structure).
1837 */
1838template <class D>
1839class Backupable : public Shareable <D>
1840{
1841public:
1842
1843 Backupable() : Shareable <D> (), mBackupData (NULL) {}
1844
1845 void free()
1846 {
1847 AssertMsg (this->mData || !mBackupData, ("backup must be NULL if data is NULL"));
1848 rollback();
1849 Shareable <D>::free();
1850 }
1851
1852 D *detach()
1853 {
1854 AssertMsg (this->mData || !mBackupData, ("backup must be NULL if data is NULL"));
1855 rollback();
1856 return Shareable <D>::detach();
1857 }
1858
1859 void share (const Backupable &data)
1860 {
1861 AssertMsg (!data.isBackedUp(), ("data to share must not be backed up"));
1862 if (!data.isBackedUp())
1863 Shareable <D>::share (data.mData);
1864 }
1865
1866 /**
1867 * Stores the current data pointer in the backup area, allocates new data
1868 * using the copy constructor on current data and makes new data active.
1869 */
1870 void backup()
1871 {
1872 AssertMsg (this->mData, ("data must not be NULL"));
1873 if (this->mData && !mBackupData)
1874 {
1875 mBackupData = this->mData;
1876 this->mData = new D (*mBackupData);
1877 }
1878 }
1879
1880 /**
1881 * Deletes new data created by #backup() and restores previous data pointer
1882 * stored in the backup area, making it active again.
1883 */
1884 void rollback()
1885 {
1886 if (this->mData && mBackupData)
1887 {
1888 delete this->mData;
1889 this->mData = mBackupData;
1890 mBackupData = NULL;
1891 }
1892 }
1893
1894 /**
1895 * Commits current changes by deleting backed up data and clearing up the
1896 * backup area. The new data pointer created by #backup() remains active
1897 * and becomes the only managed pointer.
1898 *
1899 * This method is much faster than #commitCopy() (just a single pointer
1900 * assignment operation), but makes the previous data pointer invalid
1901 * (because it is freed). For this reason, this method must not be
1902 * used if it's possible that data managed by this instance is shared with
1903 * some other Shareable instance. See #commitCopy().
1904 */
1905 void commit()
1906 {
1907 if (this->mData && mBackupData)
1908 {
1909 if (!this->mIsShared)
1910 delete mBackupData;
1911 mBackupData = NULL;
1912 this->mIsShared = false;
1913 }
1914 }
1915
1916 /**
1917 * Commits current changes by assigning new data to the previous data
1918 * pointer stored in the backup area using the assignment operator.
1919 * New data is deleted, the backup area is cleared and the previous data
1920 * pointer becomes active and the only managed pointer.
1921 *
1922 * This method is slower than #commit(), but it keeps the previous data
1923 * pointer valid (i.e. new data is copied to the same memory location).
1924 * For that reason it's safe to use this method on instances that share
1925 * managed data with other Shareable instances.
1926 */
1927 void commitCopy()
1928 {
1929 if (this->mData && mBackupData)
1930 {
1931 *mBackupData = *(this->mData);
1932 delete this->mData;
1933 this->mData = mBackupData;
1934 mBackupData = NULL;
1935 }
1936 }
1937
1938 void assignCopy (const D *data)
1939 {
1940 AssertMsg (this->mData, ("data must not be NULL"));
1941 AssertMsg (data, ("data to copy must not be NULL"));
1942 if (this->mData && data)
1943 {
1944 if (!mBackupData)
1945 {
1946 mBackupData = this->mData;
1947 this->mData = new D (*data);
1948 }
1949 else
1950 *this->mData = *data;
1951 }
1952 }
1953
1954 void assignCopy (const Backupable &data)
1955 {
1956 assignCopy (data.mData);
1957 }
1958
1959 bool isBackedUp() const
1960 {
1961 return mBackupData != NULL;
1962 }
1963
1964 bool hasActualChanges() const
1965 {
1966 AssertMsg (this->mData, ("data must not be NULL"));
1967 return this->mData != NULL && mBackupData != NULL &&
1968 !(*this->mData == *mBackupData);
1969 }
1970
1971 D *backedUpData() const
1972 {
1973 return mBackupData;
1974 }
1975
1976protected:
1977
1978 D *mBackupData;
1979};
1980
1981#if defined VBOX_MAIN_SETTINGS_ADDONS
1982
1983/**
1984 * Settinsg API additions.
1985 */
1986namespace settings
1987{
1988
1989/// @todo once string data in Bstr and Utf8Str is auto_ref_ptr, enable the
1990/// code below
1991
1992#if 0
1993
1994/** Specialization of FromString for Bstr. */
1995template<> com::Bstr FromString <com::Bstr> (const char *aValue);
1996
1997#endif
1998
1999/** Specialization of ToString for Bstr. */
2000template<> stdx::char_auto_ptr
2001ToString <com::Bstr> (const com::Bstr &aValue, unsigned int aExtra);
2002
2003/** Specialization of FromString for Guid. */
2004template<> com::Guid FromString <com::Guid> (const char *aValue);
2005
2006/** Specialization of ToString for Guid. */
2007template<> stdx::char_auto_ptr
2008ToString <com::Guid> (const com::Guid &aValue, unsigned int aExtra);
2009
2010} /* namespace settings */
2011
2012#endif /* VBOX_MAIN_SETTINGS_ADDONS */
2013
2014#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