VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxBFE/VirtualBoxBase.h@ 44093

Last change on this file since 44093 was 41783, checked in by vboxsync, 12 years ago

Doxygen, comment typos.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.3 KB
Line 
1/** @file
2 *
3 * VBox frontends: Basic Frontend (BFE):
4 * Declarations of the BFE base classes
5 */
6
7/*
8 * Copyright (C) 2006-2007 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#ifndef ____H_VIRTUALBOXBASEIMPL
20#define ____H_VIRTUALBOXBASEIMPL
21
22#ifdef VBOXBFE_WITHOUT_COM
23# include "COMDefs.h" // Our wrapper for COM definitions left in the code
24# include <iprt/uuid.h>
25#else
26# include <VBox/com/defs.h>
27#endif
28
29#include <VBox/com/assert.h> // For the AssertComRC macro
30
31#include <iprt/alloc.h>
32#include <iprt/assert.h>
33#include <iprt/critsect.h>
34#include <iprt/string.h>
35#include <iprt/asm.h> // for ASMReturnAddress
36
37#include <list>
38#include <map>
39
40// defines
41////////////////////////////////////////////////////////////////////////////////
42
43#define VBOX_E_OBJECT_NOT_FOUND 0x80BB0001
44#define VBOX_E_INVALID_VM_STATE 0x80BB0002
45#define VBOX_E_VM_ERROR 0x80BB0003
46#define VBOX_E_FILE_ERROR 0x80BB0004
47#define VBOX_E_IPRT_ERROR 0x80BB0005
48#define VBOX_E_PDM_ERROR 0x80BB0006
49#define VBOX_E_INVALID_OBJECT_STATE 0x80BB0007
50#define VBOX_E_HOST_ERROR 0x80BB0008
51#define VBOX_E_NOT_SUPPORTED 0x80BB0009
52#define VBOX_E_XML_ERROR 0x80BB000A
53#define VBOX_E_INVALID_SESSION_STATE 0x80BB000B
54#define VBOX_E_OBJECT_IN_USE 0x80BB000C
55
56// macros and inlines
57////////////////////////////////////////////////////////////////////////////////
58
59/**
60 * A lightweight replacement for the COM setError function. I am
61 * assuming that this is only called in circumstances justifying
62 * an assertion.
63 *
64 * @returns error number
65 * @param iNum error number - this is simply returned
66 * @param pszFormat formatted error message
67 */
68static inline int setError(int iNum, const char *pszFormat, ...)
69{
70 va_list args;
71 va_start(args, pszFormat);
72 AssertMsgFailed((pszFormat, args));
73 va_end(args);
74 return iNum;
75}
76
77/**
78 * Translate an error string. We do not do translation.
79 */
80#define tr(a) a
81
82/**
83 * Assert macro wrapper.
84 *
85 * In the debug build, this macro is equivalent to Assert.
86 * In the release build, this is a no-op.
87 *
88 * @param expr Expression which should be true.
89 */
90#if defined (DEBUG)
91#define ComAssert(expr) Assert (expr)
92#else
93#define ComAssert(expr) \
94 do { } while (0)
95#endif
96
97/**
98 * AssertMsg macro wrapper.
99 *
100 * In the debug build, this macro is equivalent to AssertMsg.
101 * In the release build, this is a no-op.
102 *
103 * See ComAssert for more info.
104 *
105 * @param expr Expression which should be true.
106 * @param a printf argument list (in parenthesis).
107 */
108#if defined (DEBUG)
109#define ComAssertMsg(expr, a) AssertMsg (expr, a)
110#else
111#define ComAssertMsg(expr, a) \
112 do { } while (0)
113#endif
114
115/**
116 * AssertRC macro wrapper.
117 *
118 * In the debug build, this macro is equivalent to AssertRC.
119 * In the release build, this is a no-op.
120 *
121 * See ComAssert for more info.
122 *
123 * @param vrc VBox status code.
124 */
125#if defined (DEBUG)
126#define ComAssertRC(vrc) AssertRC (vrc)
127#else
128#define ComAssertRC(vrc) ComAssertMsgRC (vrc, ("%Rra", vrc))
129#endif
130
131/**
132 * AssertMsgRC macro wrapper.
133 *
134 * In the debug build, this macro is equivalent to AssertMsgRC.
135 * In the release build, this is a no-op.
136 *
137 * See ComAssert for more info.
138 *
139 * @param vrc VBox status code.
140 * @param msg printf argument list (in parenthesis).
141 */
142#if defined (DEBUG)
143#define ComAssertMsgRC(vrc, msg) AssertMsgRC (vrc, msg)
144#else
145#define ComAssertMsgRC(vrc, msg) ComAssertMsg (RT_SUCCESS (vrc), msg)
146#endif
147
148
149/**
150 * AssertFailed macro wrapper.
151 *
152 * In the debug build, this macro is equivalent to AssertFailed.
153 * In the release build, this is a no-op.
154 *
155 * See ComAssert for more info.
156 */
157#if defined (DEBUG)
158#define ComAssertFailed() AssertFailed()
159#else
160#define ComAssertFailed() \
161 do { } while (0)
162#endif
163
164/**
165 * AssertMsgFailed macro wrapper.
166 *
167 * In the debug build, this macro is equivalent to AssertMsgFailed.
168 * In the release build, this is a no-op.
169 *
170 * See ComAssert for more info.
171 *
172 * @param a printf argument list (in parenthesis).
173 */
174#if defined (DEBUG)
175#define ComAssertMsgFailed(a) AssertMsgFailed(a)
176#else
177#define ComAssertMsgFailed(a) \
178 do { } while (0)
179#endif
180
181/**
182 * AssertComRC macro wrapper.
183 *
184 * In the debug build, this macro is equivalent to AssertComRC.
185 * In the release build, this is a no-op.
186 *
187 * See ComAssert for more info.
188 *
189 * @param rc COM result code
190 */
191#if defined (DEBUG)
192#define ComAssertComRC(rc) AssertComRC (rc)
193#else
194#define ComAssertComRC(rc) ComAssertMsg (SUCCEEDED (rc), ("COM RC = 0x%08X\n", rc))
195#endif
196
197
198/** Special version of ComAssert that returns ret if expr fails */
199#define ComAssertRet(expr, ret) \
200 do { ComAssert (expr); if (!(expr)) return (ret); } while (0)
201/** Special version of ComAssertMsg that returns ret if expr fails */
202#define ComAssertMsgRet(expr, a, ret) \
203 do { ComAssertMsg (expr, a); if (!(expr)) return (ret); } while (0)
204/** Special version of ComAssertRC that returns ret if vrc does not succeed */
205#define ComAssertRCRet(vrc, ret) \
206 do { ComAssertRC (vrc); if (!RT_SUCCESS (vrc)) return (ret); } while (0)
207/** Special version of ComAssertMsgRC that returns ret if vrc does not succeed */
208#define ComAssertMsgRCRet(vrc, msg, ret) \
209 do { ComAssertMsgRC (vrc, msg); if (!RT_SUCCESS (vrc)) return (ret); } while (0)
210/** Special version of ComAssertFailed that returns ret */
211#define ComAssertFailedRet(ret) \
212 do { ComAssertFailed(); return (ret); } while (0)
213/** Special version of ComAssertMsgFailed that returns ret */
214#define ComAssertMsgFailedRet(msg, ret) \
215 do { ComAssertMsgFailed (msg); return (ret); } while (0)
216/** Special version of ComAssertComRC that returns ret if rc does not succeed */
217#define ComAssertComRCRet(rc, ret) \
218 do { ComAssertComRC (rc); if (!SUCCEEDED (rc)) return (ret); } while (0)
219
220
221/** Special version of ComAssert that evaulates eval and breaks if expr fails */
222#define ComAssertBreak(expr, eval) \
223 if (1) { ComAssert (expr); if (!(expr)) { eval; break; } } else do {} while (0)
224/** Special version of ComAssertMsg that evaulates eval and breaks if expr fails */
225#define ComAssertMsgBreak(expr, a, eval) \
226 if (1) { ComAssertMsg (expr, a); if (!(expr)) { eval; break; } } else do {} while (0)
227/** Special version of ComAssertRC that evaulates eval and breaks if vrc does not succeed */
228#define ComAssertRCBreak(vrc, eval) \
229 if (1) { ComAssertRC (vrc); if (!RT_SUCCESS (vrc)) { eval; break; } } else do {} while (0)
230/** Special version of ComAssertMsgRC that evaulates eval and breaks if vrc does not succeed */
231#define ComAssertMsgRCBreak(vrc, msg, eval) \
232 if (1) { ComAssertMsgRC (vrc, msg); if (!RT_SUCCESS (vrc)) { eval; break; } } else do {} while (0)
233/** Special version of ComAssertFailed that vaulates eval and breaks */
234#define ComAssertFailedBreak(eval) \
235 if (1) { ComAssertFailed(); { eval; break; } } else do {} while (0)
236/** Special version of ComAssertMsgFailed that vaulates eval and breaks */
237#define ComAssertMsgFailedBreak(msg, eval) \
238 if (1) { ComAssertMsgFailed (msg); { eval; break; } } else do {} while (0)
239/** Special version of ComAssertComRC that vaulates eval and breaks if rc does not succeed */
240#define ComAssertComRCBreak(rc, eval) \
241 if (1) { ComAssertComRC (rc); if (!SUCCEEDED (rc)) { eval; break; } } else do {} while (0)
242
243/**
244 * Checks whether this object is ready or not. Objects are typically ready
245 * after they are successfully created by their parent objects and become
246 * not ready when the respective parent itsef becomes not ready or gets
247 * destroyed while a reference to the child is still held by the caller
248 * (which prevents it from destruction).
249 *
250 * When this object is not ready, the macro sets error info and returns
251 * E_UNEXPECTED (the translatable error message is defined in null context).
252 * Otherwise, the macro does nothing.
253 *
254 * This macro <b>must</b> be used at the beginning of all interface methods
255 * (right after entering the class lock) in classes derived from both
256 * VirtualBoxBase.
257 */
258#define CHECK_READY() \
259 do { \
260 if (!isReady()) \
261 return setError (E_UNEXPECTED, tr ("The object is not ready")); \
262 } while (0)
263
264/**
265 * Declares an empty constructor and destructor for the given class.
266 * This is useful to prevent the compiler from generating the default
267 * ctor and dtor, which in turn allows to use forward class statements
268 * (instead of including their header files) when declaring data members of
269 * non-fundamental types with constructors (which are always called implicitly
270 * by constructors and by the destructor of the class).
271 *
272 * This macro is to be palced within (the public section of) the class
273 * declaration. Its counterpart, DEFINE_EMPTY_CTOR_DTOR, must be placed
274 * somewhere in one of the translation units (usually .cpp source files).
275 *
276 * @param cls class to declare a ctor and dtor for
277 */
278#define DECLARE_EMPTY_CTOR_DTOR(cls) cls(); ~cls();
279
280/**
281 * Defines an empty constructor and destructor for the given class.
282 * See DECLARE_EMPTY_CTOR_DTOR for more info.
283 */
284#define DEFINE_EMPTY_CTOR_DTOR(cls) \
285 cls::cls () {}; cls::~cls () {};
286
287#define VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(cls, iface)
288
289////////////////////////////////////////////////////////////////////////////////
290
291namespace stdx
292{
293 /**
294 * A wrapper around the container that owns pointers it stores.
295 *
296 * @note
297 * Ownership is recognized only when destructing the container!
298 * Pointers are not deleted when erased using erase() etc.
299 *
300 * @param container
301 * class that meets Container requirements (for example, an instance of
302 * std::list<>, std::vector<> etc.). The given class must store
303 * pointers (for example, std::list <MyType *>).
304 */
305 template <typename container>
306 class ptr_container : public container
307 {
308 public:
309 ~ptr_container()
310 {
311 for (typename container::iterator it = container::begin();
312 it != container::end();
313 ++ it)
314 delete (*it);
315 }
316 };
317}
318
319////////////////////////////////////////////////////////////////////////////////
320
321class ATL_NO_VTABLE VirtualBoxBase
322{
323
324public:
325 VirtualBoxBase()
326 {
327 mReady = false;
328 RTCritSectInit(&mCritSec);
329 }
330 virtual ~VirtualBoxBase()
331 {
332 RTCritSectDelete(&mCritSec);
333 }
334
335 /**
336 * Virtual uninitialization method. Called during parent object's
337 * uninitialization, if the given subclass instance is a dependent child of
338 * a class derived from VirtualBoxBaseWithChildren (@sa
339 * VirtualBoxBaseWithChildren::addDependentChild). In this case, this
340 * method's implementation must call setReady (false),
341 */
342 virtual void uninit() {}
343
344 // lock the object
345 void lock()
346 {
347 RTCritSectEnter(&mCritSec);
348 }
349 // unlock the object
350 void unlock()
351 {
352 RTCritSectLeave(&mCritSec);
353 }
354
355 /** Returns true when the current thread owns this object's lock. */
356 bool isLockedOnCurrentThread()
357 {
358 return RTCritSectIsOwner (&mCritSec);
359 }
360
361 /**
362 * Helper class to make safe locking / unlocking.
363 * The constructor, given the VirtualBoxBase pointer, safely acquires the
364 * lock protecting its data. This lock will be released automatically
365 * when the instance goes out of scope (block, function etc.).
366 *
367 * @note
368 * An instance of this class must be declared as a local variable,
369 * otherwise the optimizer will most likely destruct it right after
370 * creation (but not at the end of the block), so the lock will be
371 * released immediately.
372 */
373 class AutoLock
374 {
375 public:
376
377 #if defined(RT_STRICT)
378 # define ___CritSectEnter(cs) RTCritSectEnterDebug((cs), (RTUINTPTR)ASMReturnAddress(), "return address >>>", 0, __PRETTY_FUNCTION__)
379 #else
380 # define ___CritSectEnter(cs) RTCritSectEnter((cs))
381 #endif
382
383 /** Internal lock handle */
384 class Handle
385 {
386 public:
387 Handle (RTCRITSECT &critSect) : lock (critSect) {}
388 private:
389 RTCRITSECT &lock;
390 friend class AutoLock;
391 };
392
393 AutoLock() : mLock (NULL), mLevel (0), mLeftLevel (0) {}
394
395 AutoLock (VirtualBoxBase *that)
396 : mLock (that ? &that->mCritSec : NULL)
397 , mLevel (0), mLeftLevel (0)
398 {
399 if (mLock)
400 {
401 ___CritSectEnter (mLock);
402 ++ mLevel;
403 }
404 }
405
406 AutoLock (RTCRITSECT &critSect)
407 : mLock (&critSect), mLevel (0), mLeftLevel (0)
408 {
409 if (mLock)
410 {
411 ___CritSectEnter (mLock);
412 ++ mLevel;
413 }
414 }
415
416 AutoLock (const Handle &handle)
417 : mLock (&handle.lock), mLevel (0), mLeftLevel (0)
418 {
419 if (mLock)
420 {
421 ___CritSectEnter (mLock);
422 ++ mLevel;
423 }
424 }
425
426 ~AutoLock()
427 {
428 if (mLock)
429 {
430 if (mLeftLevel)
431 {
432 mLeftLevel -= mLevel;
433 mLevel = 0;
434 for (; mLeftLevel; -- mLeftLevel)
435 RTCritSectEnter (mLock);
436 }
437 AssertMsg (mLevel <= 1, ("Lock level > 1: %d\n", mLevel));
438 for (; mLevel; -- mLevel)
439 RTCritSectLeave (mLock);
440 }
441 }
442
443 /**
444 * Tries to acquire the lock or increases the lock level
445 * if the lock is already owned by this thread.
446 */
447 void lock()
448 {
449 if (mLock)
450 {
451 AssertMsgReturn (mLeftLevel == 0, ("lock() after leave()\n"), (void) 0);
452 ___CritSectEnter (mLock);
453 ++ mLevel;
454 }
455 }
456
457 /**
458 * Decreases the lock level. If the level goes to zero, the lock
459 * is released by the current thread.
460 */
461 void unlock()
462 {
463 if (mLock)
464 {
465 AssertMsgReturn (mLevel > 0, ("Lock level is zero\n"), (void) 0);
466 AssertMsgReturn (mLeftLevel == 0, ("lock() after leave()\n"), (void) 0);
467 -- mLevel;
468 RTCritSectLeave (mLock);
469 }
470 }
471
472 /**
473 * Causes the current thread to completely release the lock
474 * (including locks acquired by all other instances of this class
475 * referring to the same object or handle). #enter() must be called
476 * to acquire the lock back and restore all lock levels.
477 */
478 void leave()
479 {
480 if (mLock)
481 {
482 AssertMsg (mLevel > 0, ("Lock level is zero\n"));
483 AssertMsgReturn (mLeftLevel == 0, ("leave() w/o enter()\n"), (void) 0);
484 mLeftLevel = RTCritSectGetRecursion (mLock);
485 for (uint32_t left = mLeftLevel; left; -- left)
486 RTCritSectLeave (mLock);
487 Assert (mLeftLevel >= mLevel);
488 }
489 }
490
491 /**
492 * Causes the current thread to acquire the lock again and restore
493 * all lock levels after calling #leave().
494 */
495 void enter()
496 {
497 if (mLock)
498 {
499 AssertMsg (mLevel > 0, ("Lock level is zero\n"));
500 AssertMsgReturn (mLeftLevel > 0, ("enter() w/o leave()\n"), (void) 0);
501 for (; mLeftLevel; -- mLeftLevel)
502 ___CritSectEnter (mLock);
503 }
504 }
505
506 uint32_t level() const { return mLevel; }
507
508 bool isNull() const { return mLock == NULL; }
509 bool operator !() const { return isNull(); }
510
511 bool belongsTo (VirtualBoxBase *that) const
512 {
513 return that && &that->mCritSec == mLock;
514 }
515
516 private:
517
518 AutoLock (const AutoLock &that); // disabled
519 AutoLock &operator = (const AutoLock &that); // disabled
520
521 RTCRITSECT *mLock;
522 uint32_t mLevel;
523 uint32_t mLeftLevel;
524
525 #undef ___CritSectEnter
526 };
527
528 // sets the ready state of the object
529 void setReady(bool ready)
530 {
531 mReady = ready;
532 }
533 // get the ready state of the object
534 bool isReady()
535 {
536 return mReady;
537 }
538
539 /**
540 * Translates the given text string according to the currently installed
541 * translation table and current context. The current context is determined
542 * by the context parameter. Additionally, a comment to the source text
543 * string text can be given. This comment (which is NULL by default)
544 * is helpful in situations where it is necessary to distinguish between
545 * two or more semantically different roles of the same source text in the
546 * same context.
547 *
548 * @param context the context of the translation
549 * @param sourceText the string to translate
550 * @param comment the comment to the string (NULL means no comment)
551 *
552 * @return
553 * the translated version of the source string in UTF-8 encoding,
554 * or the source string itself if the translation is not found
555 * in the given context.
556 */
557 static const char *translate (const char *context, const char *sourceText,
558 const char *comment = 0);
559
560private:
561
562 // flag determining whether an object is ready
563 // for usage, i.e. methods may be called
564 bool mReady;
565 // mutex semaphore to lock the object
566 RTCRITSECT mCritSec;
567};
568
569////////////////////////////////////////////////////////////////////////////////
570
571/**
572 * Simple template that manages data structure allocation/deallocation
573 * and supports data pointer sharing (the instance that shares the pointer is
574 * not responsible for memory deallocation as opposed to the instance that
575 * owns it).
576 */
577template <class D>
578class Shareable
579{
580public:
581
582 Shareable() : mData (NULL), mIsShared (FALSE) {}
583 ~Shareable() { free(); }
584
585 void allocate() { attach (new D); }
586
587 virtual void free() {
588 if (mData) {
589 if (!mIsShared)
590 delete mData;
591 mData = NULL;
592 mIsShared = false;
593 }
594 }
595
596 void attach (D *pData) {
597 AssertMsg (pData, ("new data must not be NULL"));
598 if (pData && mData != pData) {
599 if (mData && !mIsShared)
600 delete mData;
601 mData = pData;
602 mIsShared = false;
603 }
604 }
605
606 void attach (Shareable &Data) {
607 AssertMsg (
608 Data.mData == mData || !Data.mIsShared,
609 ("new data must not be shared")
610 );
611 if (this != &Data && !Data.mIsShared) {
612 attach (Data.mData);
613 Data.mIsShared = true;
614 }
615 }
616
617 void share (D *pData) {
618 AssertMsg (pData, ("new data must not be NULL"));
619 if (mData != pData) {
620 if (mData && !mIsShared)
621 delete mData;
622 mData = pData;
623 mIsShared = true;
624 }
625 }
626
627 void share (const Shareable &Data) { share (Data.mData); }
628
629 void attachCopy (const D *pData) {
630 AssertMsg (pData, ("data to copy must not be NULL"));
631 if (pData)
632 attach (new D (*pData));
633 }
634
635 void attachCopy (const Shareable &Data) {
636 attachCopy (Data.mData);
637 }
638
639 virtual D *detach() {
640 D *d = mData;
641 mData = NULL;
642 mIsShared = false;
643 return d;
644 }
645
646 D *data() const {
647 return mData;
648 }
649
650 D *operator->() const {
651 AssertMsg (mData, ("data must not be NULL"));
652 return mData;
653 }
654
655 bool isNull() const { return mData == NULL; }
656 bool operator!() const { return isNull(); }
657
658 bool isShared() const { return mIsShared; }
659
660protected:
661
662 D *mData;
663 bool mIsShared;
664};
665
666/**
667 * Simple template that enhances Shareable<> and supports data
668 * backup/rollback/commit (using the copy constructor of the managed data
669 * structure).
670 */
671template <class D>
672class Backupable : public Shareable <D>
673{
674public:
675
676 Backupable() : Shareable <D> (), mBackupData (NULL) {}
677
678 void free()
679 {
680 AssertMsg (this->mData || !mBackupData, ("backup must be NULL if data is NULL"));
681 rollback();
682 Shareable <D>::free();
683 }
684
685 D *detach()
686 {
687 AssertMsg (this->mData || !mBackupData, ("backup must be NULL if data is NULL"));
688 rollback();
689 return Shareable <D>::detach();
690 }
691
692 void share (const Backupable &data)
693 {
694 AssertMsg (!data.isBackedUp(), ("data to share must not be backed up"));
695 if (!data.isBackedUp())
696 Shareable <D>::share (data.mData);
697 }
698
699 /**
700 * Stores the current data pointer in the backup area, allocates new data
701 * using the copy constructor on current data and makes new data active.
702 */
703 void backup()
704 {
705 AssertMsg (this->mData, ("data must not be NULL"));
706 if (this->mData && !mBackupData)
707 {
708 mBackupData = this->mData;
709 this->mData = new D (*mBackupData);
710 }
711 }
712
713 /**
714 * Deletes new data created by #backup() and restores previous data pointer
715 * stored in the backup area, making it active again.
716 */
717 void rollback()
718 {
719 if (this->mData && mBackupData)
720 {
721 delete this->mData;
722 this->mData = mBackupData;
723 mBackupData = NULL;
724 }
725 }
726
727 /**
728 * Commits current changes by deleting backed up data and clearing up the
729 * backup area. The new data pointer created by #backup() remains active
730 * and becomes the only managed pointer.
731 *
732 * This method is much faster than #commitCopy() (just a single pointer
733 * assignment operation), but makes the previous data pointer invalid
734 * (because it is freed). For this reason, this method must not be
735 * used if it's possible that data managed by this instance is shared with
736 * some other Shareable instance. See #commitCopy().
737 */
738 void commit()
739 {
740 if (this->mData && mBackupData)
741 {
742 if (!this->mIsShared)
743 delete mBackupData;
744 mBackupData = NULL;
745 this->mIsShared = false;
746 }
747 }
748
749 /**
750 * Commits current changes by assigning new data to the previous data
751 * pointer stored in the backup area using the assignment operator.
752 * New data is deleted, the backup area is cleared and the previous data
753 * pointer becomes active and the only managed pointer.
754 *
755 * This method is slower than #commit(), but it keeps the previous data
756 * pointer valid (i.e. new data is copied to the same memory location).
757 * For that reason it's safe to use this method on instances that share
758 * managed data with other Shareable instances.
759 */
760 void commitCopy()
761 {
762 if (this->mData && mBackupData)
763 {
764 *mBackupData = *(this->mData);
765 delete this->mData;
766 this->mData = mBackupData;
767 mBackupData = NULL;
768 }
769 }
770
771 void assignCopy (const D *data)
772 {
773 AssertMsg (this->mData, ("data must not be NULL"));
774 AssertMsg (data, ("data to copy must not be NULL"));
775 if (this->mData && data)
776 {
777 if (!mBackupData)
778 {
779 mBackupData = this->mData;
780 this->mData = new D (*data);
781 }
782 else
783 *this->mData = *data;
784 }
785 }
786
787 void assignCopy (const Backupable &data)
788 {
789 assignCopy (data.mData);
790 }
791
792 bool isBackedUp() const
793 {
794 return mBackupData != NULL;
795 }
796
797 bool hasActualChanges() const
798 {
799 AssertMsg (this->mData, ("data must not be NULL"));
800 return this->mData != NULL && mBackupData != NULL &&
801 !(*this->mData == *mBackupData);
802 }
803
804 D *backedUpData() const
805 {
806 return mBackupData;
807 }
808
809protected:
810
811 D *mBackupData;
812};
813
814#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