84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync/** @file
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync *
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * VirtualBox object state handling definitions
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync */
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync/*
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * Copyright (C) 2006-2014 Oracle Corporation
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync *
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * available from http://www.virtualbox.org. This file is free software;
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * you can redistribute it and/or modify it under the terms of the GNU
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * General Public License (GPL) as published by the Free Software
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync */
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync#ifndef ____H_OBJECTSTATE
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync#define ____H_OBJECTSTATE
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync#include "VBox/com/defs.h"
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync#include "VBox/com/AutoLock.h"
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync// Forward declaration needed, but nothing more.
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsyncclass VirtualBoxBase;
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync////////////////////////////////////////////////////////////////////////////////
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync//
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync// ObjectState
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync//
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync////////////////////////////////////////////////////////////////////////////////
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync/**
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * Thec functionality implemented by this class is the primary object state
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * (used by VirtualBoxBase and thus part of all API classes) that indicates
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * if the object is ready to serve the calls, and if not, what stage it is
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * currently at. Here is the primary state diagram:
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync *
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * +-------------------------------------------------------+
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * | |
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * | (InitFailed) -----------------------+ |
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * | ^ | |
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * v | v |
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * [*] ---> NotReady ----> (InInit) -----> Ready -----> (InUninit) ----+
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * ^ |
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * | v
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * | Limited
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * | |
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * +-------+
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync *
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * The object is fully operational only when its state is Ready. The Limited
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * state means that only some vital part of the object is operational, and it
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * requires some sort of reinitialization to become fully operational. The
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * NotReady state means the object is basically dead: it either was not yet
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * initialized after creation at all, or was uninitialized and is waiting to be
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * destroyed when the last reference to it is released. All other states are
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * transitional.
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync *
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * The NotReady->InInit->Ready, NotReady->InInit->Limited and
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * NotReady->InInit->InitFailed transition is done by the AutoInitSpan smart
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * class.
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync *
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * The Limited->InInit->Ready, Limited->InInit->Limited and
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * Limited->InInit->InitFailed transition is done by the AutoReinitSpan smart
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * class.
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync *
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * The Ready->InUninit->NotReady and InitFailed->InUninit->NotReady
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * transitions are done by the AutoUninitSpan smart class.
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync *
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * In order to maintain the primary state integrity and declared functionality
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * the following rules apply everywhere:
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync *
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * 1) Use the above Auto*Span classes to perform state transitions. See the
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * individual class descriptions for details.
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync *
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * 2) All public methods of subclasses (i.e. all methods that can be called
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * directly, not only from within other methods of the subclass) must have a
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * standard prolog as described in the AutoCaller and AutoLimitedCaller
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * documentation. Alternatively, they must use #addCaller() and
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * #releaseCaller() directly (and therefore have both the prolog and the
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * epilog), but this is not recommended because it is easy to forget the
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * matching release, e.g. returning before reaching the call.
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync */
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsyncclass ObjectState
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync{
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsyncpublic:
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync enum State { NotReady, Ready, InInit, InUninit, InitFailed, Limited };
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync ObjectState(VirtualBoxBase *aObj);
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync ~ObjectState();
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync State getState();
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync HRESULT addCaller(bool aLimited = false);
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync void releaseCaller();
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync bool autoInitSpanConstructor(State aExpectedState);
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync void autoInitSpanDestructor(State aNewState);
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync State autoUninitSpanConstructor();
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync void autoUninitSpanDestructor();
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsyncprivate:
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync ObjectState();
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync void setState(State aState);
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync /** Pointer to the managed object, mostly for error signalling or debugging
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * purposes, not used much. Guaranteed to be valid during the lifetime of
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync * this object, no need to mess with refcount. */
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync VirtualBoxBase *mObj;
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync /** Primary state of this object */
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync State mState;
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync /** Thread that caused the last state change */
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync RTTHREAD mStateChangeThread;
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync /** Total number of active calls to this object */
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync unsigned mCallers;
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync /** Posted when the number of callers drops to zero */
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync RTSEMEVENT mZeroCallersSem;
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync /** Posted when the object goes from InInit/InUninit to some other state */
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync RTSEMEVENTMULTI mInitUninitSem;
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync /** Number of threads waiting for mInitUninitDoneSem */
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync unsigned mInitUninitWaiters;
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync /** Protects access to state related data members */
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync util::RWLockHandle mStateLock;
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync};
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync
84029357bc8c5780585a1cd1b40319bbc23d022fvboxsync#endif // !____H_OBJECTSTATE