VirtualBox

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

Last change on this file since 26853 was 26853, checked in by vboxsync, 15 years ago

VBoxBFE: Attempt to fix burn caused by r58109.

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

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