VirtualBox

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

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

FE/BFE: more clean-up to reduce the difference between MouseImpl.cpp in Main and VBoxBFE

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