VirtualBox

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

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

Ported r27277:27975 (array support) from branches/dmik/s2.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 77.9 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 *
1474 * @deprecated Use VirtualBoxBaseWithChildrenNEXT for new classes.
1475 */
1476class VirtualBoxBaseWithChildren : public VirtualBoxBase
1477{
1478public:
1479
1480 VirtualBoxBaseWithChildren()
1481 : mUninitDoneSem (NIL_RTSEMEVENT), mChildrenLeft (0)
1482 {
1483 RTCritSectInit (&mMapLock);
1484 }
1485
1486 virtual ~VirtualBoxBaseWithChildren()
1487 {
1488 RTCritSectDelete (&mMapLock);
1489 }
1490
1491 /**
1492 * Adds the given child to the map of dependent children.
1493 * Intended to be called from the child's init() method,
1494 * from under the child's lock.
1495 *
1496 * @param C the child object to add (must inherit VirtualBoxBase AND
1497 * implement some interface)
1498 */
1499 template <class C>
1500 void addDependentChild (C *child)
1501 {
1502 AssertReturn (child, (void) 0);
1503 addDependentChild (child, child);
1504 }
1505
1506 /**
1507 * Removes the given child from the map of dependent children.
1508 * Must be called <b>after<b> the child has called setReady(false), and
1509 * <b>not</b> from under the child object's lock.
1510 *
1511 * @param C the child object to remove (must inherit VirtualBoxBase AND
1512 * implement some interface)
1513 */
1514 template <class C>
1515 void removeDependentChild (C *child)
1516 {
1517 AssertReturn (child, (void) 0);
1518 /// @todo (r=dmik) the below check (and the relevant comment above)
1519 // seems to be not necessary any more once we completely switch to
1520 // the NEXT locking scheme. This requires altering removeDependentChild()
1521 // and uninitDependentChildren() as well (due to the new state scheme,
1522 // there is a separate mutex for state transition, so calling the
1523 // child's uninit() from under the children map lock should not produce
1524 // dead-locks any more).
1525 Assert (!child->isLockedOnCurrentThread());
1526 removeDependentChild (ComPtr <IUnknown> (child));
1527 }
1528
1529protected:
1530
1531 void uninitDependentChildren();
1532
1533 VirtualBoxBase *getDependentChild (const ComPtr <IUnknown> &unk);
1534
1535private:
1536
1537 void addDependentChild (const ComPtr <IUnknown> &unk, VirtualBoxBase *child);
1538 void removeDependentChild (const ComPtr <IUnknown> &unk);
1539
1540 typedef std::map <IUnknown *, VirtualBoxBase *> DependentChildren;
1541 DependentChildren mDependentChildren;
1542
1543 RTCRITSECT mMapLock;
1544 RTSEMEVENT mUninitDoneSem;
1545 unsigned mChildrenLeft;
1546};
1547
1548////////////////////////////////////////////////////////////////////////////////
1549
1550/**
1551 *
1552 * Base class to track VirtualBoxBaseNEXT chlidren of the component.
1553 *
1554 * This class is a preferrable VirtualBoxBase replacement for components that
1555 * operate with collections of child components. It gives two useful
1556 * possibilities:
1557 *
1558 * <ol><li>
1559 * Given an IUnknown instance, it's possible to quickly determine
1560 * whether this instance represents a child object created by the given
1561 * component, and if so, get a valid VirtualBoxBase pointer to the child
1562 * object. The returned pointer can be then safely casted to the
1563 * actual class of the child object (to get access to its "internal"
1564 * non-interface methods) provided that no other child components implement
1565 * the same initial interface IUnknown is queried from.
1566 * </li><li>
1567 * When the parent object uninitializes itself, it can easily unintialize
1568 * all its VirtualBoxBase derived children (using their
1569 * VirtualBoxBase::uninit() implementations). This is done simply by
1570 * calling the #uninitDependentChildren() method.
1571 * </li></ol>
1572 *
1573 * In order to let the above work, the following must be done:
1574 * <ol><li>
1575 * When a child object is initialized, it calls #addDependentChild() of
1576 * its parent to register itself within the list of dependent children.
1577 * </li><li>
1578 * When a child object it is uninitialized, it calls
1579 * #removeDependentChild() to unregister itself. Since the child's
1580 * uninitialization may originate both from this method and from the child
1581 * itself calling its uninit() on another thread at the same time, please
1582 * make sure that #removeDependentChild() is called:
1583 * <ul><li>
1584 * after the child has successfully entered AutoUninitSpan -- to make
1585 * sure this method is called only once for the given child object
1586 * transitioning from Ready to NotReady. A failure to do so will at
1587 * least likely cause an assertion ("Failed to remove the child from
1588 * the map").
1589 * </li><li>
1590 * outside the child object's lock -- to avoid guaranteed deadlocks
1591 * caused by different lock order: (child_lock, map_lock) in uninit()
1592 * and (map_lock, child_lock) in this method.
1593 * </li></ul>
1594 * </li></ol>
1595 *
1596 * Note that children added by #addDependentChild() are <b>weakly</b> referenced
1597 * (i.e. AddRef() is not called), so when a child object is deleted externally
1598 * (because it's reference count goes to zero), it will automatically remove
1599 * itself from the map of dependent children provided that it follows the rules
1600 * described here.
1601 *
1602 * @note Once again: because of weak referencing, deadlocks and assertions are
1603 * very likely if #addDependentChild() or #removeDependentChild() are used
1604 * incorrectly (called at inappropriate times). Check the above rules once
1605 * more.
1606 *
1607 * @todo This is a VirtualBoxBaseWithChildren equivalent that uses the
1608 * VirtualBoxBaseNEXT implementation. Will completely supercede
1609 * VirtualBoxBaseWithChildren after the old VirtualBoxBase implementation
1610 * has gone.
1611 */
1612class VirtualBoxBaseWithChildrenNEXT : public VirtualBoxBaseNEXT
1613{
1614public:
1615
1616 VirtualBoxBaseWithChildrenNEXT()
1617 : mUninitDoneSem (NIL_RTSEMEVENT), mChildrenLeft (0)
1618 {}
1619
1620 virtual ~VirtualBoxBaseWithChildrenNEXT()
1621 {}
1622
1623 /**
1624 * Adds the given child to the map of dependent children.
1625 *
1626 * Typically called from the child's init() method, from within the
1627 * AutoInitSpan scope. Otherwise, VirtualBoxBase::AutoCaller must be
1628 * used on @a aChild to make sure it is not uninitialized during this
1629 * method's call.
1630 *
1631 * @param aChild Child object to add (must inherit VirtualBoxBase AND
1632 * implement some interface).
1633 */
1634 template <class C>
1635 void addDependentChild (C *aChild)
1636 {
1637 AssertReturnVoid (aChild);
1638 doAddDependentChild (ComPtr <IUnknown> (aChild), aChild);
1639 }
1640
1641 /**
1642 * Removes the given child from the map of dependent children.
1643 *
1644 * Make sure this method is called after the child has successfully entered
1645 * AutoUninitSpan and outside the child lock.
1646 *
1647 * If called not from within the AutoUninitSpan scope,
1648 * VirtualBoxBase::AutoCaller must be used on @a aChild to make sure it is
1649 * not uninitialized during this method's call.
1650 *
1651 * @param aChild Child object to remove (must inherit VirtualBoxBase AND
1652 * implement some interface).
1653 */
1654 template <class C>
1655 void removeDependentChild (C *aChild)
1656 {
1657 AssertReturnVoid (aChild);
1658 Assert (!aChild->isLockedOnCurrentThread());
1659 doRemoveDependentChild (ComPtr <IUnknown> (aChild));
1660 }
1661
1662protected:
1663
1664 void uninitDependentChildren();
1665
1666 VirtualBoxBaseNEXT *getDependentChild (const ComPtr <IUnknown> &aUnk);
1667
1668private:
1669
1670 /// @todo temporarily reinterpret VirtualBoxBase * as VirtualBoxBaseNEXT *
1671 // until ported HardDisk and Progress to the new scheme.
1672 void doAddDependentChild (IUnknown *aUnk, VirtualBoxBase *aChild)
1673 {
1674 doAddDependentChild (aUnk,
1675 reinterpret_cast <VirtualBoxBaseNEXT *> (aChild));
1676 }
1677
1678 void doAddDependentChild (IUnknown *aUnk, VirtualBoxBaseNEXT *aChild);
1679 void doRemoveDependentChild (IUnknown *aUnk);
1680
1681 typedef std::map <IUnknown *, VirtualBoxBaseNEXT *> DependentChildren;
1682 DependentChildren mDependentChildren;
1683
1684 RTSEMEVENT mUninitDoneSem;
1685 size_t mChildrenLeft;
1686
1687 /* Protects all the fields above */
1688 AutoLock::Handle mMapLock;
1689};
1690
1691////////////////////////////////////////////////////////////////////////////////
1692
1693/**
1694 * Base class to track component's chlidren of some particular type.
1695 *
1696 * This class is similar to VirtualBoxBaseWithChildren, with the exception
1697 * that all children must be of the same type. For this reason, it's not
1698 * necessary to use a map to store children, so a list is used instead.
1699 *
1700 * As opposed to VirtualBoxBaseWithChildren, children added by
1701 * #addDependentChild() are <b>strongly</b> referenced, so that they cannot
1702 * be externally destructed until #removeDependentChild() is called.
1703 * For this reason, strict rules of calling #removeDependentChild() don't
1704 * apply to instances of this class -- it can be called anywhere in the
1705 * child's uninit() implementation.
1706 *
1707 * @param C type of child objects (must inherit VirtualBoxBase AND
1708 * implement some interface)
1709 *
1710 * @deprecated Use VirtualBoxBaseWithTypedChildrenNEXT for new classes.
1711 */
1712template <class C>
1713class VirtualBoxBaseWithTypedChildren : public VirtualBoxBase
1714{
1715public:
1716
1717 typedef std::list <ComObjPtr <C> > DependentChildren;
1718
1719 VirtualBoxBaseWithTypedChildren() : mInUninit (false) {}
1720
1721 virtual ~VirtualBoxBaseWithTypedChildren() {}
1722
1723 /**
1724 * Adds the given child to the list of dependent children.
1725 * Must be called from the child's init() method,
1726 * from under the child's lock.
1727 *
1728 * @param C the child object to add (must inherit VirtualBoxBase AND
1729 * implement some interface)
1730 */
1731 void addDependentChild (C *child)
1732 {
1733 AssertReturn (child, (void) 0);
1734
1735 AutoLock alock (mMapLock);
1736 if (mInUninit)
1737 return;
1738
1739 mDependentChildren.push_back (child);
1740 }
1741
1742 /**
1743 * Removes the given child from the list of dependent children.
1744 * Must be called from the child's uninit() method,
1745 * under the child's lock.
1746 *
1747 * @param C the child object to remove (must inherit VirtualBoxBase AND
1748 * implement some interface)
1749 */
1750 void removeDependentChild (C *child)
1751 {
1752 AssertReturn (child, (void) 0);
1753
1754 AutoLock alock (mMapLock);
1755 if (mInUninit)
1756 return;
1757
1758 mDependentChildren.remove (child);
1759 }
1760
1761protected:
1762
1763 /**
1764 * Returns an internal lock handle to lock the list of children
1765 * returned by #dependentChildren() using AutoLock:
1766 * <code>
1767 * AutoLock alock (dependentChildrenLock());
1768 * </code>
1769 */
1770 AutoLock::Handle &dependentChildrenLock() const { return mMapLock; }
1771
1772 /**
1773 * Returns the read-only list of all dependent children.
1774 * @note
1775 * Access the returned list (iterate, get size etc.) only after
1776 * doing |AutoLock alock (dependentChildrenLock());|!
1777 */
1778 const DependentChildren &dependentChildren() const { return mDependentChildren; }
1779
1780 /**
1781 * Uninitializes all dependent children registered with #addDependentChild().
1782 *
1783 * @note
1784 * This method will call uninit() methods of children. If these methods
1785 * access the parent object, uninitDependentChildren() must be called
1786 * either at the beginning of the parent uninitialization sequence (when
1787 * it is still operational) or after setReady(false) is called to
1788 * indicate the parent is out of action.
1789 */
1790 void uninitDependentChildren()
1791 {
1792 AutoLock alock (this);
1793 AutoLock mapLock (mMapLock);
1794
1795 if (mDependentChildren.size())
1796 {
1797 // set flag to ignore #removeDependentChild() called from child->uninit()
1798 mInUninit = true;
1799
1800 // leave the locks to let children waiting for #removeDependentChild() run
1801 mapLock.leave();
1802 alock.leave();
1803
1804 for (typename DependentChildren::iterator it = mDependentChildren.begin();
1805 it != mDependentChildren.end(); ++ it)
1806 {
1807 C *child = (*it);
1808 Assert (child);
1809 if (child)
1810 child->uninit();
1811 }
1812 mDependentChildren.clear();
1813
1814 alock.enter();
1815 mapLock.enter();
1816
1817 mInUninit = false;
1818 }
1819 }
1820
1821 /**
1822 * Removes (detaches) all dependent children registered with
1823 * #addDependentChild(), without uninitializing them.
1824 *
1825 * @note This method must be called from under the main object's lock
1826 */
1827 void removeDependentChildren()
1828 {
1829 AutoLock alock (mMapLock);
1830 mDependentChildren.clear();
1831 }
1832
1833private:
1834
1835 DependentChildren mDependentChildren;
1836
1837 bool mInUninit;
1838 mutable AutoLock::Handle mMapLock;
1839};
1840
1841////////////////////////////////////////////////////////////////////////////////
1842
1843/**
1844 * Base class to track component's chlidren of the particular type.
1845 *
1846 * This class is similar to VirtualBoxBaseWithChildren, with the exception that
1847 * all children must be of the same type. For this reason, it's not necessary to
1848 * use a map to store children, so a list is used instead.
1849 *
1850 * As opposed to VirtualBoxBaseWithChildren, children added by
1851 * #addDependentChild() are <b>strongly</b> referenced, so that they cannot be
1852 * externally deleted until #removeDependentChild() is called. For this
1853 * reason, strict rules of calling #removeDependentChild() don't apply to
1854 * instances of this class -- it can be called anywhere in the child's uninit()
1855 * implementation.
1856 *
1857 * @param C Type of child objects (must inherit VirtualBoxBase AND implementsome
1858 * interface).
1859 *
1860 * @todo This is a VirtualBoxBaseWithChildren equivalent that uses the
1861 * VirtualBoxBaseNEXT implementation. Will completely supercede
1862 * VirtualBoxBaseWithChildren after the old VirtualBoxBase implementation
1863 * has gone.
1864 */
1865template <class C>
1866class VirtualBoxBaseWithTypedChildrenNEXT : public VirtualBoxBaseNEXT
1867{
1868public:
1869
1870 typedef std::list <ComObjPtr <C> > DependentChildren;
1871
1872 VirtualBoxBaseWithTypedChildrenNEXT() : mInUninit (false) {}
1873
1874 virtual ~VirtualBoxBaseWithTypedChildrenNEXT() {}
1875
1876 /**
1877 * Adds the given child to the list of dependent children.
1878 *
1879 * VirtualBoxBase::AutoCaller must be used on @a aChild to make sure it is
1880 * not uninitialized during this method's call.
1881 *
1882 * @param aChild Child object to add (must inherit VirtualBoxBase AND
1883 * implement some interface).
1884 */
1885 void addDependentChild (C *aChild)
1886 {
1887 AssertReturnVoid (aChild);
1888
1889 AutoLock alock (mMapLock);
1890 if (mInUninit)
1891 return;
1892
1893 mDependentChildren.push_back (aChild);
1894 }
1895
1896 /**
1897 * Removes the given child from the list of dependent children.
1898 *
1899 * VirtualBoxBase::AutoCaller must be used on @a aChild to make sure it is
1900 * not uninitialized during this method's call.
1901 *
1902 * @param aChild the child object to remove (must inherit VirtualBoxBase
1903 * AND implement some interface).
1904 */
1905 void removeDependentChild (C *aChild)
1906 {
1907 AssertReturnVoid (aChild);
1908
1909 AutoLock alock (mMapLock);
1910 if (mInUninit)
1911 return;
1912
1913 mDependentChildren.remove (aChild);
1914 }
1915
1916protected:
1917
1918 /**
1919 * Returns an internal lock handle used to lock the list of children
1920 * returned by #dependentChildren(). This lock is to be used by AutoLock as
1921 * follows:
1922 * <code>
1923 * AutoLock alock (dependentChildrenLock());
1924 * </code>
1925 */
1926 AutoLock::Handle &dependentChildrenLock() const { return mMapLock; }
1927
1928 /**
1929 * Returns the read-only list of all dependent children.
1930 *
1931 * @note Access the returned list (iterate, get size etc.) only after doing
1932 * AutoLock alock (dependentChildrenLock())!
1933 */
1934 const DependentChildren &dependentChildren() const { return mDependentChildren; }
1935
1936 void uninitDependentChildren();
1937
1938 /**
1939 * Removes (detaches) all dependent children registered with
1940 * #addDependentChild(), without uninitializing them.
1941 *
1942 * @note This method must be called from under the main object's lock.
1943 */
1944 void removeDependentChildren()
1945 {
1946 /// @todo why?..
1947 AssertReturnVoid (isLockedOnCurrentThread());
1948
1949 AutoLock alock (mMapLock);
1950 mDependentChildren.clear();
1951 }
1952
1953private:
1954
1955 DependentChildren mDependentChildren;
1956
1957 bool mInUninit;
1958
1959 /* Protects the two fields above */
1960 mutable AutoLock::Handle mMapLock;
1961};
1962
1963////////////////////////////////////////////////////////////////////////////////
1964
1965/// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
1966/**
1967 * Simple template that manages data structure allocation/deallocation
1968 * and supports data pointer sharing (the instance that shares the pointer is
1969 * not responsible for memory deallocation as opposed to the instance that
1970 * owns it).
1971 */
1972template <class D>
1973class Shareable
1974{
1975public:
1976
1977 Shareable() : mData (NULL), mIsShared (FALSE) {}
1978 ~Shareable() { free(); }
1979
1980 void allocate() { attach (new D); }
1981
1982 virtual void free() {
1983 if (mData) {
1984 if (!mIsShared)
1985 delete mData;
1986 mData = NULL;
1987 mIsShared = false;
1988 }
1989 }
1990
1991 void attach (D *data) {
1992 AssertMsg (data, ("new data must not be NULL"));
1993 if (data && mData != data) {
1994 if (mData && !mIsShared)
1995 delete mData;
1996 mData = data;
1997 mIsShared = false;
1998 }
1999 }
2000
2001 void attach (Shareable &data) {
2002 AssertMsg (
2003 data.mData == mData || !data.mIsShared,
2004 ("new data must not be shared")
2005 );
2006 if (this != &data && !data.mIsShared) {
2007 attach (data.mData);
2008 data.mIsShared = true;
2009 }
2010 }
2011
2012 void share (D *data) {
2013 AssertMsg (data, ("new data must not be NULL"));
2014 if (mData != data) {
2015 if (mData && !mIsShared)
2016 delete mData;
2017 mData = data;
2018 mIsShared = true;
2019 }
2020 }
2021
2022 void share (const Shareable &data) { share (data.mData); }
2023
2024 void attachCopy (const D *data) {
2025 AssertMsg (data, ("data to copy must not be NULL"));
2026 if (data)
2027 attach (new D (*data));
2028 }
2029
2030 void attachCopy (const Shareable &data) {
2031 attachCopy (data.mData);
2032 }
2033
2034 virtual D *detach() {
2035 D *d = mData;
2036 mData = NULL;
2037 mIsShared = false;
2038 return d;
2039 }
2040
2041 D *data() const {
2042 return mData;
2043 }
2044
2045 D *operator->() const {
2046 AssertMsg (mData, ("data must not be NULL"));
2047 return mData;
2048 }
2049
2050 bool isNull() const { return mData == NULL; }
2051 bool operator!() const { return isNull(); }
2052
2053 bool isShared() const { return mIsShared; }
2054
2055protected:
2056
2057 D *mData;
2058 bool mIsShared;
2059};
2060
2061/// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
2062/**
2063 * Simple template that enhances Shareable<> and supports data
2064 * backup/rollback/commit (using the copy constructor of the managed data
2065 * structure).
2066 */
2067template <class D>
2068class Backupable : public Shareable <D>
2069{
2070public:
2071
2072 Backupable() : Shareable <D> (), mBackupData (NULL) {}
2073
2074 void free()
2075 {
2076 AssertMsg (this->mData || !mBackupData, ("backup must be NULL if data is NULL"));
2077 rollback();
2078 Shareable <D>::free();
2079 }
2080
2081 D *detach()
2082 {
2083 AssertMsg (this->mData || !mBackupData, ("backup must be NULL if data is NULL"));
2084 rollback();
2085 return Shareable <D>::detach();
2086 }
2087
2088 void share (const Backupable &data)
2089 {
2090 AssertMsg (!data.isBackedUp(), ("data to share must not be backed up"));
2091 if (!data.isBackedUp())
2092 Shareable <D>::share (data.mData);
2093 }
2094
2095 /**
2096 * Stores the current data pointer in the backup area, allocates new data
2097 * using the copy constructor on current data and makes new data active.
2098 */
2099 void backup()
2100 {
2101 AssertMsg (this->mData, ("data must not be NULL"));
2102 if (this->mData && !mBackupData)
2103 {
2104 mBackupData = this->mData;
2105 this->mData = new D (*mBackupData);
2106 }
2107 }
2108
2109 /**
2110 * Deletes new data created by #backup() and restores previous data pointer
2111 * stored in the backup area, making it active again.
2112 */
2113 void rollback()
2114 {
2115 if (this->mData && mBackupData)
2116 {
2117 delete this->mData;
2118 this->mData = mBackupData;
2119 mBackupData = NULL;
2120 }
2121 }
2122
2123 /**
2124 * Commits current changes by deleting backed up data and clearing up the
2125 * backup area. The new data pointer created by #backup() remains active
2126 * and becomes the only managed pointer.
2127 *
2128 * This method is much faster than #commitCopy() (just a single pointer
2129 * assignment operation), but makes the previous data pointer invalid
2130 * (because it is freed). For this reason, this method must not be
2131 * used if it's possible that data managed by this instance is shared with
2132 * some other Shareable instance. See #commitCopy().
2133 */
2134 void commit()
2135 {
2136 if (this->mData && mBackupData)
2137 {
2138 if (!this->mIsShared)
2139 delete mBackupData;
2140 mBackupData = NULL;
2141 this->mIsShared = false;
2142 }
2143 }
2144
2145 /**
2146 * Commits current changes by assigning new data to the previous data
2147 * pointer stored in the backup area using the assignment operator.
2148 * New data is deleted, the backup area is cleared and the previous data
2149 * pointer becomes active and the only managed pointer.
2150 *
2151 * This method is slower than #commit(), but it keeps the previous data
2152 * pointer valid (i.e. new data is copied to the same memory location).
2153 * For that reason it's safe to use this method on instances that share
2154 * managed data with other Shareable instances.
2155 */
2156 void commitCopy()
2157 {
2158 if (this->mData && mBackupData)
2159 {
2160 *mBackupData = *(this->mData);
2161 delete this->mData;
2162 this->mData = mBackupData;
2163 mBackupData = NULL;
2164 }
2165 }
2166
2167 void assignCopy (const D *data)
2168 {
2169 AssertMsg (this->mData, ("data must not be NULL"));
2170 AssertMsg (data, ("data to copy must not be NULL"));
2171 if (this->mData && data)
2172 {
2173 if (!mBackupData)
2174 {
2175 mBackupData = this->mData;
2176 this->mData = new D (*data);
2177 }
2178 else
2179 *this->mData = *data;
2180 }
2181 }
2182
2183 void assignCopy (const Backupable &data)
2184 {
2185 assignCopy (data.mData);
2186 }
2187
2188 bool isBackedUp() const
2189 {
2190 return mBackupData != NULL;
2191 }
2192
2193 bool hasActualChanges() const
2194 {
2195 AssertMsg (this->mData, ("data must not be NULL"));
2196 return this->mData != NULL && mBackupData != NULL &&
2197 !(*this->mData == *mBackupData);
2198 }
2199
2200 D *backedUpData() const
2201 {
2202 return mBackupData;
2203 }
2204
2205protected:
2206
2207 D *mBackupData;
2208};
2209
2210#if defined VBOX_MAIN_SETTINGS_ADDONS
2211
2212/**
2213 * Settinsg API additions.
2214 */
2215namespace settings
2216{
2217
2218/// @todo once string data in Bstr and Utf8Str is auto_ref_ptr, enable the
2219/// code below
2220
2221#if 0
2222
2223/** Specialization of FromString for Bstr. */
2224template<> com::Bstr FromString <com::Bstr> (const char *aValue);
2225
2226#endif
2227
2228/** Specialization of ToString for Bstr. */
2229template<> stdx::char_auto_ptr
2230ToString <com::Bstr> (const com::Bstr &aValue, unsigned int aExtra);
2231
2232/** Specialization of FromString for Guid. */
2233template<> com::Guid FromString <com::Guid> (const char *aValue);
2234
2235/** Specialization of ToString for Guid. */
2236template<> stdx::char_auto_ptr
2237ToString <com::Guid> (const com::Guid &aValue, unsigned int aExtra);
2238
2239} /* namespace settings */
2240
2241#endif /* VBOX_MAIN_SETTINGS_ADDONS */
2242
2243#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