VirtualBoxBase.h revision 240f7d7012a5f64bcde850bcf048531a710d81cf
/** @file
*
* VBox frontends: Basic Frontend (BFE):
* Declarations of the BFE base classes
*/
/*
* Copyright (C) 2006-2007 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
#ifndef ____H_VIRTUALBOXBASEIMPL
#define ____H_VIRTUALBOXBASEIMPL
#ifdef VBOXBFE_WITHOUT_COM
# include "COMDefs.h" // Our wrapper for COM definitions left in the code
#else
#endif
#include <iprt/critsect.h>
#include <list>
#include <map>
// macros and inlines
////////////////////////////////////////////////////////////////////////////////
/**
* A lightweight replacement for the COM setError function. I am
* assuming that this is only called in circumstances justifying
* an assertion.
*
* @returns error number
* @param iNum error number - this is simply returned
* @param pszFormat formatted error message
*/
{
return iNum;
}
/**
* Translate an error string. We do not do translation.
*/
#define tr(a) a
/**
* A special version of the Assert macro to be used within VirtualBoxBase
* subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
*
* In the debug build, this macro is equivalent to Assert.
* In the release build, this macro uses |setError (E_FAIL, ...)| to set the
* error info from the asserted expression.
*
* @see VirtualBoxSupportErrorInfoImpl::setError
*
* @param expr Expression which should be true.
*/
#if defined (DEBUG)
#else
do { } while (0)
#endif
/**
* A special version of the AssertMsg macro to be used within VirtualBoxBase
* subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
*
* See ComAssert for more info.
*
* @param expr Expression which should be true.
* @param a printf argument list (in parenthesis).
*/
#if defined (DEBUG)
#else
#define ComAssertMsg(expr, a) \
do { } while (0)
#endif
/**
* A special version of the AssertRC macro to be used within VirtualBoxBase
* subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
*
* See ComAssert for more info.
*
* @param vrc VBox status code.
*/
#if defined (DEBUG)
#else
#endif
/**
* A special version of the AssertMsgRC macro to be used within VirtualBoxBase
* subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
*
* See ComAssert for more info.
*
* @param vrc VBox status code.
* @param msg printf argument list (in parenthesis).
*/
#if defined (DEBUG)
#else
#endif
/**
* A special version of the AssertFailed macro to be used within VirtualBoxBase
* subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
*
* See ComAssert for more info.
*/
#if defined (DEBUG)
#define ComAssertFailed() AssertFailed()
#else
#define ComAssertFailed() \
do { } while (0)
#endif
/**
* A special version of the AssertMsgFailed macro to be used within VirtualBoxBase
* subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
*
* See ComAssert for more info.
*
* @param a printf argument list (in parenthesis).
*/
#if defined (DEBUG)
#define ComAssertMsgFailed(a) AssertMsgFailed(a)
#else
#define ComAssertMsgFailed(a) \
do { } while (0)
#endif
/**
* A special version of the AssertComRC macro to be used within VirtualBoxBase
* subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
*
* See ComAssert for more info.
*
* @param rc COM result code
*/
#if defined (DEBUG)
#else
#endif
/** Special version of ComAssert that returns ret if expr fails */
/** Special version of ComAssertMsg that returns ret if expr fails */
/** Special version of ComAssertRC that returns ret if vrc does not succeed */
/** Special version of ComAssertMsgRC that returns ret if vrc does not succeed */
/** Special version of ComAssertFailed that returns ret */
#define ComAssertFailedRet(ret) \
do { ComAssertFailed(); return (ret); } while (0)
/** Special version of ComAssertMsgFailed that returns ret */
/** Special version of ComAssertComRC that returns ret if rc does not succeed */
/** Special version of ComAssert that evaulates eval and breaks if expr fails */
/** Special version of ComAssertMsg that evaulates eval and breaks if expr fails */
/** Special version of ComAssertRC that evaulates eval and breaks if vrc does not succeed */
/** Special version of ComAssertMsgRC that evaulates eval and breaks if vrc does not succeed */
/** Special version of ComAssertFailed that vaulates eval and breaks */
#define ComAssertFailedBreak(eval) \
/** Special version of ComAssertMsgFailed that vaulates eval and breaks */
/** Special version of ComAssertComRC that vaulates eval and breaks if rc does not succeed */
/**
* Checks whether this object is ready or not. Objects are typically ready
* after they are successfully created by their parent objects and become
* not ready when the respective parent itsef becomes not ready or gets
* destroyed while a reference to the child is still held by the caller
* (which prevents it from destruction).
*
* When this object is not ready, the macro sets error info and returns
* E_UNEXPECTED (the translatable error message is defined in null context).
* Otherwise, the macro does nothing.
*
* This macro <b>must</b> be used at the beginning of all interface methods
* (right after entering the class lock) in classes derived from both
* VirtualBoxBase and VirtualBoxSupportErrorInfoImpl.
*/
#define CHECK_READY() \
do { \
if (!isReady()) \
} while (0)
/**
* Declares an empty construtor and destructor for the given class.
* This is useful to prevent the compiler from generating the default
* ctor and dtor, which in turn allows to use forward class statements
* (instead of including their header files) when declaring data members of
* non-fundamental types with constructors (which are always called implicitly
* by constructors and by the destructor of the class).
*
* This macro is to be palced within (the public section of) the class
* declaration. Its counterpart, DEFINE_EMPTY_CTOR_DTOR, must be placed
* somewhere in one of the translation units (usually .cpp source files).
*
* @param cls class to declare a ctor and dtor for
*/
/**
* Defines an empty construtor and destructor for the given class.
* See DECLARE_EMPTY_CTOR_DTOR for more info.
*/
#define DEFINE_EMPTY_CTOR_DTOR(cls) \
////////////////////////////////////////////////////////////////////////////////
{
/**
* A wrapper around the container that owns pointers it stores.
*
* @note
* Ownership is recognized only when destructing the container!
* Pointers are not deleted when erased using erase() etc.
*
* @param container
* class that meets Container requirements (for example, an instance of
* std::list<>, std::vector<> etc.). The given class must store
* pointers (for example, std::list <MyType *>).
*/
{
{
++ it)
}
};
};
////////////////////////////////////////////////////////////////////////////////
{
{
mReady = false;
}
{
}
/**
* Virtual unintialization method. Called during parent object's
* uninitialization, if the given subclass instance is a dependent child of
* a class dervived from VirtualBoxBaseWithChildren (@sa
* VirtualBoxBaseWithChildren::addDependentChild). In this case, this
* method's impelemtation must call setReady (false),
*/
// lock the object
void lock()
{
}
// unlock the object
void unlock()
{
}
/** Returns true when the current thread owns this object's lock. */
bool isLockedOnCurrentThread()
{
return RTCritSectIsOwner (&mCritSec);
}
/**
* Helper class to make safe locking / unlocking.
* The constructor, given the VirtualBoxBase pointer, safely acquires the
* lock protecting its data. This lock will be released automatically
* when the instance goes out of scope (block, funciton etc.).
*
* @note
* An instance of this class must be declared as a local variable,
* otherwise the optimizer will most likely destruct it right after
* creation (but not at the end of the block), so the lock will be
* released immediately.
*/
{
#if defined(DEBUG)
# define ___CritSectEnter(cs) \
RTCritSectEnterDebug ((cs), \
"AutoLock::lock()/enter() return address >>>", 0, \
#else
#endif
/** Internal lock handle */
{
};
, mLevel (0), mLeftLevel (0)
{
if (mLock)
{
++ mLevel;
}
}
{
if (mLock)
{
++ mLevel;
}
}
{
if (mLock)
{
++ mLevel;
}
}
~AutoLock()
{
if (mLock)
{
if (mLeftLevel)
{
mLeftLevel -= mLevel;
mLevel = 0;
for (; mLeftLevel; -- mLeftLevel)
}
}
}
/**
* Tries to acquire the lock or increases the lock level
* if the lock is already owned by this thread.
*/
void lock()
{
if (mLock)
{
++ mLevel;
}
}
/**
* Decreases the lock level. If the level goes to zero, the lock
* is released by the current thread.
*/
void unlock()
{
if (mLock)
{
-- mLevel;
}
}
/**
* Causes the current thread to completely release the lock
* (including locks acquired by all other instances of this class
* referring to the same object or handle). #enter() must be called
* to acquire the lock back and restore all lock levels.
*/
void leave()
{
if (mLock)
{
}
}
/**
* Causes the current thread to acquire the lock again and restore
* all lock levels after calling #leave().
*/
void enter()
{
if (mLock)
{
for (; mLeftLevel; -- mLeftLevel)
}
}
{
}
};
// sets the ready state of the object
{
}
// get the ready state of the object
bool isReady()
{
return mReady;
}
/**
* Translates the given text string according to the currently installed
* translation table and current context. The current context is determined
* by the context parameter. Additionally, a comment to the source text
* string text can be given. This comment (which is NULL by default)
* is helpful in sutuations where it is necessary to distinguish between
* two or more semantically different roles of the same source text in the
* same context.
*
* @param context the context of the the translation
* @param sourceText the string to translate
* @param comment the comment to the string (NULL means no comment)
*
* @return
* the translated version of the source string in UTF-8 encoding,
* or the source string itself if the translation is not found
* in the given context.
*/
const char *comment = 0);
// flag determining whether an object is ready
// for usage, i.e. methods may be called
bool mReady;
// mutex semaphore to lock the object
};
////////////////////////////////////////////////////////////////////////////////
/**
* Simple template that manages data structure allocation/deallocation
* and supports data pointer sharing (the instance that shares the pointer is
* not responsible for memory deallocation as opposed to the instance that
* owns it).
*/
{
if (mData) {
if (!mIsShared)
mIsShared = false;
}
}
mIsShared = false;
}
}
("new data must not be shared")
);
}
}
mIsShared = true;
}
}
void attachCopy (const D *data) {
if (data)
}
}
D *d = mData;
mIsShared = false;
return d;
}
D *data() const {
return mData;
}
D *operator->() const {
return mData;
}
D *mData;
bool mIsShared;
};
/**
* Simple template that enhances Shareable<> and supports data
* structure).
*/
{
void free()
{
rollback();
}
D *detach()
{
rollback();
}
{
if (!data.isBackedUp())
}
/**
* Stores the current data pointer in the backup area, allocates new data
* using the copy constructor on current data and makes new data active.
*/
void backup()
{
{
}
}
/**
* Deletes new data created by #backup() and restores previous data pointer
* stored in the backup area, making it active again.
*/
void rollback()
{
{
mBackupData = NULL;
}
}
/**
* Commits current changes by deleting backed up data and clearing up the
* backup area. The new data pointer created by #backup() remains active
* and becomes the only managed pointer.
*
* This method is much faster than #commitCopy() (just a single pointer
* assignment operation), but makes the previous data pointer invalid
* (because it is freed). For this reason, this method must not be
* used if it's possible that data managed by this instance is shared with
* some other Shareable instance. See #commitCopy().
*/
void commit()
{
{
mBackupData = NULL;
}
}
/**
* Commits current changes by assigning new data to the previous data
* pointer stored in the backup area using the assignment operator.
* New data is deleted, the backup area is cleared and the previous data
* pointer becomes active and the only managed pointer.
*
* This method is slower than #commit(), but it keeps the previous data
* pointer valid (i.e. new data is copied to the same memory location).
* For that reason it's safe to use this method on instances that share
* managed data with other Shareable instances.
*/
void commitCopy()
{
{
mBackupData = NULL;
}
}
void assignCopy (const D *data)
{
{
if (!mBackupData)
{
}
else
}
}
{
}
bool isBackedUp() const
{
return mBackupData != NULL;
}
bool hasActualChanges() const
{
}
D *backedUpData() const
{
return mBackupData;
}
D *mBackupData;
};
#endif // ____H_VIRTUALBOXBASEIMPL