VirtualBoxBase.cpp revision 26d2a42f095ded346df2e41cc4837cb426b4753a
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync * VirtualBox COM base classes implementation
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * available from http://www.virtualbox.org. This file is free software;
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync * additional information or have any questions.
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync#else /* !defined (VBOX_WITH_XPCOM) */
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync/// @todo remove when VirtualBoxErrorInfo goes away from here
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync#endif /* !defined (VBOX_WITH_XPCOM) */
134a71c1528b56afe4db843ab63ec5a5b849535bvboxsync// VirtualBoxBaseProto methods
134a71c1528b56afe4db843ab63ec5a5b849535bvboxsync////////////////////////////////////////////////////////////////////////////////
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync// util::Lockable interface
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsyncRWLockHandle *VirtualBoxBaseProto::lockHandle() const
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync /* lazy initialization */
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync AssertCompile (sizeof (RWLockHandle *) == sizeof (void *));
9ad5e3912962c3dbccc1afc4e7d62890fe906814vboxsync if (!ASMAtomicCmpXchgPtr ((void * volatile *) &mObjectLock, objLock, NULL))
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync objLock = (RWLockHandle *) ASMAtomicReadPtr ((void * volatile *) &mObjectLock);
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * Increments the number of calls to this object by one.
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * After this method succeeds, it is guaranted that the object will remain
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * in the Ready (or in the Limited) state at least until #releaseCaller() is
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * This method is intended to mark the beginning of sections of code within
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * methods of COM objects that depend on the readiness (Ready) state. The
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * Ready state is a primary "ready to serve" state. Usually all code that
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * works with component's data depends on it. On practice, this means that
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * almost every public method, setter or getter of the object should add
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * itself as an object's caller at the very beginning, to protect from an
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * unexpected uninitialization that may happen on a different thread.
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * Besides the Ready state denoting that the object is fully functional,
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * there is a special Limited state. The Limited state means that the object
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * is still functional, but its functionality is limited to some degree, so
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * not all operations are possible. The @a aLimited argument to this method
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * determines whether the caller represents this limited functionality or
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * This method succeeeds (and increments the number of callers) only if the
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * current object's state is Ready. Otherwise, it will return E_ACCESSDENIED
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * to indicate that the object is not operational. There are two exceptions
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * from this rule:
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * <li>If the @a aLimited argument is |true|, then this method will also
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * succeeed if the object's state is Limited (or Ready, of course).
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * <li>If this method is called from the same thread that placed
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * the object to InInit or InUninit state (i.e. either from within the
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * AutoInitSpan or AutoUninitSpan scope), it will succeed as well (but
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * will not increase the number of callers).
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * Normally, calling addCaller() never blocks. However, if this method is
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * called by a thread created from within the AutoInitSpan scope and this
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * scope is still active (i.e. the object state is InInit), it will block
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * until the AutoInitSpan destructor signals that it has finished
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * initialization.
134a71c1528b56afe4db843ab63ec5a5b849535bvboxsync * Also, addCaller() will block if the object is probing uninitialization on
9ad5e3912962c3dbccc1afc4e7d62890fe906814vboxsync * another thread with AutoMayUninitSpan (i.e. the object state is MayUninit).
134a71c1528b56afe4db843ab63ec5a5b849535bvboxsync * And again, the block will last until the AutoMayUninitSpan destructor signals
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * that it has finished probing and the object is either ready again or will
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * uninitialize shortly (so that addCaller() will fail).
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * When this method returns a failure, the caller must not use the object
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * and should return the failed result code to its own caller.
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * @param aState Where to store the current object's state (can be
50fdc90dae026b2086f85b0f028aa63dd6bbe14evboxsync * used in overriden methods to determine the cause of
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * the failure).
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * @param aLimited |true| to add a limited caller.
50fdc90dae026b2086f85b0f028aa63dd6bbe14evboxsync * @return S_OK on success or E_ACCESSDENIED on failure.
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * @note It is preferrable to use the #addLimitedCaller() rather than
50fdc90dae026b2086f85b0f028aa63dd6bbe14evboxsync * calling this method with @a aLimited = |true|, for better
50fdc90dae026b2086f85b0f028aa63dd6bbe14evboxsync * self-descriptiveness.
50fdc90dae026b2086f85b0f028aa63dd6bbe14evboxsync * @sa #addLimitedCaller()
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * @sa #releaseCaller()
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsyncHRESULT VirtualBoxBaseProto::addCaller (State *aState /* = NULL */,
6f516ad9911d9037a18778742caa955fe362f8ffvboxsync if (mState == Ready || (aLimited && mState == Limited))
6f516ad9911d9037a18778742caa955fe362f8ffvboxsync /* if Ready or allows Limited, increase the number of callers */
6f516ad9911d9037a18778742caa955fe362f8ffvboxsync if (mState == InInit || mState == MayUninit || mState == InUninit)
6f516ad9911d9037a18778742caa955fe362f8ffvboxsync /* Called from the same thread that is doing AutoInitSpan or
6f516ad9911d9037a18778742caa955fe362f8ffvboxsync * AutoUninitSpan or AutoMayUninitSpan, just succeed */
6f516ad9911d9037a18778742caa955fe362f8ffvboxsync /* One of the two:
6f516ad9911d9037a18778742caa955fe362f8ffvboxsync * 1) addCaller() is called by a "child" thread while the "parent"
6f516ad9911d9037a18778742caa955fe362f8ffvboxsync * thread is still doing AutoInitSpan/AutoReinitSpan, so wait for
6f516ad9911d9037a18778742caa955fe362f8ffvboxsync * the state to become either Ready/Limited or InitFailed (in
6f516ad9911d9037a18778742caa955fe362f8ffvboxsync * case of init failure).
++ mCallers;
"Waiting for AutoInitSpan/AutoReinitSpan to "
if (-- mInitUninitWaiters == 0)
-- mCallers;
if (aState)
return rc;
-- mCallers;
-- mCallers;
if (mCallers == 0)
if (!mOk)
if (!mOk)
if (mSucceeded)
mInitFailed = true;
if (mUninitDone)
mObj));
if (mUninitDone)
, mAcceptUninit (false)
case Ready:
case MayUninit:
mAlreadyInProgress = true;
if (!mAcceptUninit)
const char *comment)
return sourceText;
if (!fn)
#if defined (__GNUC__)
if (start)
++ counter;
-- counter;
if (aLogIt)
preserve));
E_FAIL);
if (aWarning)
#if !defined (VBOX_WITH_XPCOM)
if (preserve)
if (preserve)
/// @todo (r=dmik) see todo in VirtualBoxBase.h, in
if (child)
return NULL;
return NULL;
++ mChildrenLeft;
/// @todo (r=dmik) see todo in VirtualBoxBase.h, in
-- mChildrenLeft;
if (mChildrenLeft == 0)
while (count != 0)
if (child)
-- count;
return NULL;
return NULL;
#if defined VBOX_MAIN_SETTINGS_ADDONS
namespace settings
throw ENoValue();
return result;
return result;
throw ENoValue();
return result;