VirtualBox

Changeset 25202 in vbox for trunk/src


Ignore:
Timestamp:
Dec 4, 2009 7:13:21 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
55683
Message:

Main: make ParallelPort instance data private and make it use the XML settings struct for simplicity

Location:
trunk/src/VBox/Main
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/ParallelPortImpl.cpp

    r25149 r25202  
    3030#include <VBox/settings.h>
    3131
     32////////////////////////////////////////////////////////////////////////////////
     33//
     34// ParallelPort private data definition
     35//
     36////////////////////////////////////////////////////////////////////////////////
     37
     38struct ParallelPort::Data
     39{
     40    Data()
     41    { }
     42
     43    const ComObjPtr<Machine, ComWeakRef>    pMachine;
     44    const ComObjPtr<ParallelPort>           pPeer;
     45
     46    Backupable<settings::ParallelPort>      bd;
     47};
     48
    3249// constructor / destructor
    3350/////////////////////////////////////////////////////////////////////////////
    3451
    35 DEFINE_EMPTY_CTOR_DTOR (ParallelPort)
    36 
    3752HRESULT ParallelPort::FinalConstruct()
    3853{
     
    5368 *  @param aParent  Handle of the parent object.
    5469 */
    55 HRESULT ParallelPort::init (Machine *aParent, ULONG aSlot)
     70HRESULT ParallelPort::init(Machine *aParent, ULONG aSlot)
    5671{
    5772    LogFlowThisFunc(("aParent=%p, aSlot=%d\n", aParent, aSlot));
     
    6378    AssertReturn(autoInitSpan.isOk(), E_FAIL);
    6479
    65     unconst(mParent) = aParent;
    66     /* mPeer is left null */
    67 
    68     mData.allocate();
     80    m = new Data;
     81
     82    unconst(m->pMachine) = aParent;
     83    /* m->pPeer is left null */
     84
     85    m->bd.allocate();
    6986
    7087    /* initialize data */
    71     mData->mSlot = aSlot;
     88    m->bd->ulSlot = aSlot;
    7289
    7390    /* Confirm a successful initialization */
     
    87104 *  @note Locks @a aThat object for reading.
    88105 */
    89 HRESULT ParallelPort::init (Machine *aParent, ParallelPort *aThat)
     106HRESULT ParallelPort::init(Machine *aParent, ParallelPort *aThat)
    90107{
    91108    LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
     
    97114    AssertReturn(autoInitSpan.isOk(), E_FAIL);
    98115
    99     unconst(mParent) = aParent;
    100     unconst(mPeer) = aThat;
     116    m = new Data;
     117
     118    unconst(m->pMachine) = aParent;
     119    unconst(m->pPeer) = aThat;
    101120
    102121    AutoCaller thatCaller (aThat);
    103122    AssertComRCReturnRC(thatCaller.rc());
    104123
    105     AutoReadLock thatLock (aThat);
    106     mData.share (aThat->mData);
     124    AutoReadLock thatLock(aThat);
     125    m->bd.share(aThat->m->bd);
    107126
    108127    /* Confirm a successful initialization */
     
    119138 *  @note Locks @a aThat object for reading.
    120139 */
    121 HRESULT ParallelPort::initCopy (Machine *aParent, ParallelPort *aThat)
     140HRESULT ParallelPort::initCopy(Machine *aParent, ParallelPort *aThat)
    122141{
    123142    LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
     
    129148    AssertReturn(autoInitSpan.isOk(), E_FAIL);
    130149
    131     unconst(mParent) = aParent;
    132     /* mPeer is left null */
    133 
    134     AutoCaller thatCaller (aThat);
     150    m = new Data;
     151
     152    unconst(m->pMachine) = aParent;
     153    /* m->pPeer is left null */
     154
     155    AutoCaller thatCaller(aThat);
    135156    AssertComRCReturnRC(thatCaller.rc());
    136157
    137     AutoReadLock thatLock (aThat);
    138     mData.attachCopy (aThat->mData);
     158    AutoReadLock thatLock(aThat);
     159    m->bd.attachCopy(aThat->m->bd);
    139160
    140161    /* Confirm a successful initialization */
     
    157178        return;
    158179
    159     mData.free();
    160 
    161     unconst(mPeer).setNull();
    162     unconst(mParent).setNull();
    163 }
    164 
    165 // public methods only for internal purposes
    166 ////////////////////////////////////////////////////////////////////////////////
    167 
    168 /**
    169  *  Loads settings from the given port node.
    170  *  May be called once right after this object creation.
    171  *
    172  *  @param aPortNode <Port> node.
    173  *
    174  *  @note Locks this object for writing.
    175  */
    176 HRESULT ParallelPort::loadSettings(const settings::ParallelPort &data)
    177 {
    178     AutoCaller autoCaller(this);
    179     AssertComRCReturnRC(autoCaller.rc());
    180 
    181     AutoWriteLock alock(this);
    182 
    183     /* Note: we assume that the default values for attributes of optional
    184      * nodes are assigned in the Data::Data() constructor and don't do it
    185      * here. It implies that this method may only be called after constructing
    186      * a new BIOSSettings object while all its data fields are in the default
    187      * values. Exceptions are fields whose creation time defaults don't match
    188      * values that should be applied when these fields are not explicitly set
    189      * in the settings file (for backwards compatibility reasons). This takes
    190      * place when a setting of a newly created object must default to A while
    191      * the same setting of an object loaded from the old settings file must
    192      * default to B. */
    193 
    194     /* enabled (required) */
    195     mData->mEnabled = data.fEnabled;
    196     /* I/O base (required) */
    197     mData->mIOBase = data.ulIOBase;
    198     /* IRQ (required) */
    199     mData->mIRQ = data.ulIRQ;
    200     /* device path (optional, defaults to null) */
    201     Bstr path(data.strPath);
    202     HRESULT rc = checkSetPath (path);
    203     if (FAILED(rc)) return rc;
    204     mData->mPath = path;
    205 
    206     return S_OK;
    207 }
    208 
    209 /**
    210  *  Saves settings to the given port node.
    211  *
    212  *  Note that the given Port node is comletely empty on input.
    213  *
    214  *  @param aPortNode <Port> node.
    215  *
    216  *  @note Locks this object for reading.
    217  */
    218 HRESULT ParallelPort::saveSettings(settings::ParallelPort &data)
    219 {
    220     AutoCaller autoCaller(this);
    221     AssertComRCReturnRC(autoCaller.rc());
    222 
    223     AutoReadLock alock(this);
    224 
    225     data.fEnabled = !!mData->mEnabled;
    226     data.ulIOBase = mData->mIOBase;
    227     data.ulIRQ = mData->mIRQ;
    228     data.strPath = mData->mPath;
    229 
    230     return S_OK;
    231 }
    232 
    233 /**
    234  *  @note Locks this object for writing.
    235  */
    236 bool ParallelPort::rollback()
    237 {
    238     /* sanity */
    239     AutoCaller autoCaller(this);
    240     AssertComRCReturn (autoCaller.rc(), false);
    241 
    242     AutoWriteLock alock(this);
    243 
    244     bool changed = false;
    245 
    246     if (mData.isBackedUp())
    247     {
    248         /* we need to check all data to see whether anything will be changed
    249          * after rollback */
    250         changed = mData.hasActualChanges();
    251         mData.rollback();
    252     }
    253 
    254     return changed;
    255 }
    256 
    257 /**
    258  *  @note Locks this object for writing, together with the peer object (also
    259  *  for writing) if there is one.
    260  */
    261 void ParallelPort::commit()
    262 {
    263     /* sanity */
    264     AutoCaller autoCaller(this);
    265     AssertComRCReturnVoid (autoCaller.rc());
    266 
    267     /* sanity too */
    268     AutoCaller peerCaller (mPeer);
    269     AssertComRCReturnVoid (peerCaller.rc());
    270 
    271     /* lock both for writing since we modify both (mPeer is "master" so locked
    272      * first) */
    273     AutoMultiWriteLock2 alock (mPeer, this);
    274 
    275     if (mData.isBackedUp())
    276     {
    277         mData.commit();
    278         if (mPeer)
    279         {
    280             /* attach new data to the peer and reshare it */
    281             mPeer->mData.attach (mData);
    282         }
    283     }
    284 }
    285 
    286 /**
    287  *  @note Locks this object for writing, together with the peer object
    288  *  represented by @a aThat (locked for reading).
    289  */
    290 void ParallelPort::copyFrom (ParallelPort *aThat)
    291 {
    292     AssertReturnVoid (aThat != NULL);
    293 
    294     /* sanity */
    295     AutoCaller autoCaller(this);
    296     AssertComRCReturnVoid (autoCaller.rc());
    297 
    298     /* sanity too */
    299     AutoCaller thatCaller (aThat);
    300     AssertComRCReturnVoid (thatCaller.rc());
    301 
    302     /* peer is not modified, lock it for reading (aThat is "master" so locked
    303      * first) */
    304     AutoMultiLock2 alock (aThat->rlock(), this->wlock());
    305 
    306     /* this will back up current data */
    307     mData.assignCopy (aThat->mData);
     180    m->bd.free();
     181
     182    unconst(m->pPeer).setNull();
     183    unconst(m->pMachine).setNull();
     184
     185    delete m;
     186    m = NULL;
    308187}
    309188
     
    320199    AutoReadLock alock(this);
    321200
    322     *aEnabled = mData->mEnabled;
     201    *aEnabled = m->bd->fEnabled;
    323202
    324203    return S_OK;
     
    333212
    334213    /* the machine needs to be mutable */
    335     Machine::AutoMutableStateDependency adep(mParent);
     214    Machine::AutoMutableStateDependency adep(m->pMachine);
    336215    if (FAILED(adep.rc())) return adep.rc();
    337216
    338217    AutoWriteLock alock(this);
    339218
    340     if (mData->mEnabled != aEnabled)
     219    if (m->bd->fEnabled != aEnabled)
    341220    {
    342221        if (aEnabled &&
    343             mData->mPath.isEmpty())
     222            m->bd->strPath.isEmpty())
    344223            return setError (E_INVALIDARG,
    345224                        tr ("Cannot enable the parallel port %d "
    346225                            "because the port path is empty or null"),
    347                         mData->mSlot);
    348 
    349         mData.backup();
    350         mData->mEnabled = aEnabled;
     226                        m->bd->ulSlot);
     227
     228        m->bd.backup();
     229        m->bd->fEnabled = aEnabled;
    351230
    352231        /* leave the lock before informing callbacks */
    353232        alock.unlock();
    354233
    355         mParent->onParallelPortChange (this);
     234        m->pMachine->onParallelPortChange (this);
    356235    }
    357236
     
    368247    AutoReadLock alock(this);
    369248
    370     *aSlot = mData->mSlot;
     249    *aSlot = m->bd->ulSlot;
    371250
    372251    return S_OK;
     
    382261    AutoReadLock alock(this);
    383262
    384     *aIRQ = mData->mIRQ;
     263    *aIRQ = m->bd->ulIRQ;
    385264
    386265    return S_OK;
     
    395274            tr ("Invalid IRQ number of the parallel port %d: "
    396275                "%lu (must be in range [0, %lu])"),
    397             mData->mSlot, aIRQ, 255);
     276            m->bd->ulSlot, aIRQ, 255);
    398277
    399278    AutoCaller autoCaller(this);
     
    401280
    402281    /* the machine needs to be mutable */
    403     Machine::AutoMutableStateDependency adep(mParent);
     282    Machine::AutoMutableStateDependency adep(m->pMachine);
    404283    if (FAILED(adep.rc())) return adep.rc();
    405284
     
    409288    bool emitChangeEvent = false;
    410289
    411     if (mData->mIRQ != aIRQ)
    412     {
    413         mData.backup();
    414         mData->mIRQ = aIRQ;
     290    if (m->bd->ulIRQ != aIRQ)
     291    {
     292        m->bd.backup();
     293        m->bd->ulIRQ = aIRQ;
    415294        emitChangeEvent = true;
    416295    }
     
    421300        alock.unlock();
    422301
    423         mParent->onParallelPortChange (this);
     302        m->pMachine->onParallelPortChange (this);
    424303    }
    425304
     
    436315    AutoReadLock alock(this);
    437316
    438     *aIOBase = mData->mIOBase;
     317    *aIOBase = m->bd->ulIOBase;
    439318
    440319    return S_OK;
     
    449328            tr ("Invalid I/O port base address of the parallel port %d: "
    450329                "%lu (must be in range [0, 0x%X])"),
    451             mData->mSlot, aIOBase, 0, 0xFFFF);
     330            m->bd->ulSlot, aIOBase, 0, 0xFFFF);
    452331
    453332    AutoCaller autoCaller(this);
     
    455334
    456335    /* the machine needs to be mutable */
    457     Machine::AutoMutableStateDependency adep(mParent);
     336    Machine::AutoMutableStateDependency adep(m->pMachine);
    458337    if (FAILED(adep.rc())) return adep.rc();
    459338
     
    463342    bool emitChangeEvent = false;
    464343
    465     if (mData->mIOBase != aIOBase)
    466     {
    467         mData.backup();
    468         mData->mIOBase = aIOBase;
     344    if (m->bd->ulIOBase != aIOBase)
     345    {
     346        m->bd.backup();
     347        m->bd->ulIOBase = aIOBase;
    469348        emitChangeEvent = true;
    470349    }
     
    475354        alock.unlock();
    476355
    477         mParent->onParallelPortChange (this);
     356        m->pMachine->onParallelPortChange (this);
    478357    }
    479358
     
    490369    AutoReadLock alock(this);
    491370
    492     mData->mPath.cloneTo(aPath);
     371    m->bd->strPath.cloneTo(aPath);
    493372
    494373    return S_OK;
     
    498377 *  Validates COMSETTER(Path) arguments.
    499378 */
    500 HRESULT ParallelPort::checkSetPath (CBSTR aPath)
     379HRESULT ParallelPort::checkSetPath(const Utf8Str &str)
    501380{
    502381    AssertReturn(isWriteLockOnCurrentThread(), E_FAIL);
    503382
    504     if (mData->mEnabled &&
    505         (aPath == NULL || *aPath == '\0'))
    506         return setError (E_INVALIDARG,
    507             tr ("Path of the parallel port %d may not be empty or null "
    508                 "when the port is enabled"),
    509             mData->mSlot);
     383    if (    m->bd->fEnabled
     384         && str.isEmpty()
     385       )
     386        return setError(E_INVALIDARG,
     387                        tr("Path of the parallel port %d may not be empty or null "
     388                           "when the port is enabled"),
     389                        m->bd->ulSlot);
    510390
    511391    return S_OK;
     
    518398
    519399    /* the machine needs to be mutable */
    520     Machine::AutoMutableStateDependency adep(mParent);
     400    Machine::AutoMutableStateDependency adep(m->pMachine);
    521401    if (FAILED(adep.rc())) return adep.rc();
    522402
    523403    AutoWriteLock alock(this);
    524404
    525     /* we treat empty as null when e.g. saving to XML, do the same here */
    526     if (aPath && *aPath == '\0')
    527         aPath = NULL;
    528 
    529     if (mData->mPath != aPath)
    530     {
    531         HRESULT rc = checkSetPath (aPath);
     405    Utf8Str str(aPath);
     406    if (str != m->bd->strPath)
     407    {
     408        HRESULT rc = checkSetPath(str);
    532409        if (FAILED(rc)) return rc;
    533410
    534         mData.backup();
    535         mData->mPath = aPath;
     411        m->bd.backup();
     412        m->bd->strPath = str;
    536413
    537414        /* leave the lock before informing callbacks */
    538415        alock.unlock();
    539416
    540         return mParent->onParallelPortChange (this);
    541     }
    542 
    543     return S_OK;
    544 }
     417        return m->pMachine->onParallelPortChange (this);
     418    }
     419
     420    return S_OK;
     421}
     422
     423// public methods only for internal purposes
     424////////////////////////////////////////////////////////////////////////////////
     425
     426/**
     427 *  Loads settings from the given port node.
     428 *  May be called once right after this object creation.
     429 *
     430 *  @param aPortNode <Port> node.
     431 *
     432 *  @note Locks this object for writing.
     433 */
     434HRESULT ParallelPort::loadSettings(const settings::ParallelPort &data)
     435{
     436    AutoCaller autoCaller(this);
     437    AssertComRCReturnRC(autoCaller.rc());
     438
     439    AutoWriteLock alock(this);
     440
     441    // simply copy
     442    *m->bd.data() = data;
     443
     444    return S_OK;
     445}
     446
     447/**
     448 *  Saves settings to the given port node.
     449 *
     450 *  Note that the given Port node is comletely empty on input.
     451 *
     452 *  @param aPortNode <Port> node.
     453 *
     454 *  @note Locks this object for reading.
     455 */
     456HRESULT ParallelPort::saveSettings(settings::ParallelPort &data)
     457{
     458    AutoCaller autoCaller(this);
     459    AssertComRCReturnRC(autoCaller.rc());
     460
     461    AutoReadLock alock(this);
     462
     463    // simply copy
     464    data = *m->bd.data();
     465
     466    return S_OK;
     467}
     468
     469bool ParallelPort::isModified()
     470{
     471    AutoWriteLock alock (this);
     472    return m->bd.isBackedUp();
     473}
     474
     475bool ParallelPort::isReallyModified()
     476{
     477    AutoWriteLock alock(this);
     478    return m->bd.hasActualChanges();
     479}
     480
     481/**
     482 *  @note Locks this object for writing.
     483 */
     484bool ParallelPort::rollback()
     485{
     486    /* sanity */
     487    AutoCaller autoCaller(this);
     488    AssertComRCReturn (autoCaller.rc(), false);
     489
     490    AutoWriteLock alock(this);
     491
     492    bool changed = false;
     493
     494    if (m->bd.isBackedUp())
     495    {
     496        /* we need to check all data to see whether anything will be changed
     497         * after rollback */
     498        changed = m->bd.hasActualChanges();
     499        m->bd.rollback();
     500    }
     501
     502    return changed;
     503}
     504
     505/**
     506 *  @note Locks this object for writing, together with the peer object (also
     507 *  for writing) if there is one.
     508 */
     509void ParallelPort::commit()
     510{
     511    /* sanity */
     512    AutoCaller autoCaller(this);
     513    AssertComRCReturnVoid (autoCaller.rc());
     514
     515    /* sanity too */
     516    AutoCaller peerCaller (m->pPeer);
     517    AssertComRCReturnVoid (peerCaller.rc());
     518
     519    /* lock both for writing since we modify both (m->pPeer is "master" so locked
     520     * first) */
     521    AutoMultiWriteLock2 alock (m->pPeer, this);
     522
     523    if (m->bd.isBackedUp())
     524    {
     525        m->bd.commit();
     526        if (m->pPeer)
     527        {
     528            /* attach new data to the peer and reshare it */
     529            m->pPeer->m->bd.attach(m->bd);
     530        }
     531    }
     532}
     533
     534/**
     535 *  @note Locks this object for writing, together with the peer object
     536 *  represented by @a aThat (locked for reading).
     537 */
     538void ParallelPort::copyFrom (ParallelPort *aThat)
     539{
     540    AssertReturnVoid (aThat != NULL);
     541
     542    /* sanity */
     543    AutoCaller autoCaller(this);
     544    AssertComRCReturnVoid (autoCaller.rc());
     545
     546    /* sanity too */
     547    AutoCaller thatCaller (aThat);
     548    AssertComRCReturnVoid (thatCaller.rc());
     549
     550    /* peer is not modified, lock it for reading (aThat is "master" so locked
     551     * first) */
     552    AutoMultiLock2 alock (aThat->rlock(), this->wlock());
     553
     554    /* this will back up current data */
     555    m->bd.assignCopy(aThat->m->bd);
     556}
     557
     558
    545559/* vi: set tabstop=4 shiftwidth=4 expandtab: */
  • trunk/src/VBox/Main/include/ParallelPortImpl.h

    r24989 r25202  
    4040{
    4141public:
    42 
    43     struct Data
    44     {
    45         Data()
    46             : mSlot (0)
    47             , mEnabled (FALSE)
    48             , mIRQ (4)
    49             , mIOBase (0x378)
    50         {}
    51 
    52         bool operator== (const Data &that) const
    53         {
    54             return this == &that ||
    55                    (mSlot == that.mSlot &&
    56                     mEnabled == that.mEnabled &&
    57                     mIRQ == that.mIRQ &&
    58                     mIOBase == that.mIOBase &&
    59                     mPath == that.mPath);
    60         }
    61 
    62         ULONG mSlot;
    63         BOOL  mEnabled;
    64         ULONG mIRQ;
    65         ULONG mIOBase;
    66         Bstr  mPath;
    67     };
    68 
    6942    VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT (ParallelPort)
    7043
     
    7952    END_COM_MAP()
    8053
    81     DECLARE_EMPTY_CTOR_DTOR (ParallelPort)
     54    ParallelPort() {}
     55    ~ParallelPort() {}
    8256
    8357    HRESULT FinalConstruct();
     
    10680    HRESULT saveSettings(settings::ParallelPort &data);
    10781
    108     bool isModified() { AutoWriteLock alock (this); return mData.isBackedUp(); }
    109     bool isReallyModified() { AutoWriteLock alock (this); return mData.hasActualChanges(); }
     82    bool isModified();
     83    bool isReallyModified();
    11084    bool rollback();
    11185    void commit();
    112     void copyFrom (ParallelPort *aThat);
     86    void copyFrom(ParallelPort *aThat);
    11387
    11488    // public methods for internal purposes only
     
    12094private:
    12195
    122     HRESULT checkSetPath (CBSTR aPath);
     96    HRESULT checkSetPath(const Utf8Str &str);
    12397
    124     const ComObjPtr<Machine, ComWeakRef> mParent;
    125     const ComObjPtr<ParallelPort> mPeer;
    126 
    127     Backupable<Data> mData;
     98    struct Data;
     99    Data *m;
    128100};
    129101
Note: See TracChangeset for help on using the changeset viewer.

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