- Timestamp:
- Dec 4, 2009 7:13:21 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 55683
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/ParallelPortImpl.cpp
r25149 r25202 30 30 #include <VBox/settings.h> 31 31 32 //////////////////////////////////////////////////////////////////////////////// 33 // 34 // ParallelPort private data definition 35 // 36 //////////////////////////////////////////////////////////////////////////////// 37 38 struct 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 32 49 // constructor / destructor 33 50 ///////////////////////////////////////////////////////////////////////////// 34 51 35 DEFINE_EMPTY_CTOR_DTOR (ParallelPort)36 37 52 HRESULT ParallelPort::FinalConstruct() 38 53 { … … 53 68 * @param aParent Handle of the parent object. 54 69 */ 55 HRESULT ParallelPort::init 70 HRESULT ParallelPort::init(Machine *aParent, ULONG aSlot) 56 71 { 57 72 LogFlowThisFunc(("aParent=%p, aSlot=%d\n", aParent, aSlot)); … … 63 78 AssertReturn(autoInitSpan.isOk(), E_FAIL); 64 79 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(); 69 86 70 87 /* initialize data */ 71 m Data->mSlot = aSlot;88 m->bd->ulSlot = aSlot; 72 89 73 90 /* Confirm a successful initialization */ … … 87 104 * @note Locks @a aThat object for reading. 88 105 */ 89 HRESULT ParallelPort::init 106 HRESULT ParallelPort::init(Machine *aParent, ParallelPort *aThat) 90 107 { 91 108 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat)); … … 97 114 AssertReturn(autoInitSpan.isOk(), E_FAIL); 98 115 99 unconst(mParent) = aParent; 100 unconst(mPeer) = aThat; 116 m = new Data; 117 118 unconst(m->pMachine) = aParent; 119 unconst(m->pPeer) = aThat; 101 120 102 121 AutoCaller thatCaller (aThat); 103 122 AssertComRCReturnRC(thatCaller.rc()); 104 123 105 AutoReadLock thatLock 106 m Data.share (aThat->mData);124 AutoReadLock thatLock(aThat); 125 m->bd.share(aThat->m->bd); 107 126 108 127 /* Confirm a successful initialization */ … … 119 138 * @note Locks @a aThat object for reading. 120 139 */ 121 HRESULT ParallelPort::initCopy 140 HRESULT ParallelPort::initCopy(Machine *aParent, ParallelPort *aThat) 122 141 { 123 142 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat)); … … 129 148 AssertReturn(autoInitSpan.isOk(), E_FAIL); 130 149 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); 135 156 AssertComRCReturnRC(thatCaller.rc()); 136 157 137 AutoReadLock thatLock 138 m Data.attachCopy (aThat->mData);158 AutoReadLock thatLock(aThat); 159 m->bd.attachCopy(aThat->m->bd); 139 160 140 161 /* Confirm a successful initialization */ … … 157 178 return; 158 179 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; 308 187 } 309 188 … … 320 199 AutoReadLock alock(this); 321 200 322 *aEnabled = m Data->mEnabled;201 *aEnabled = m->bd->fEnabled; 323 202 324 203 return S_OK; … … 333 212 334 213 /* the machine needs to be mutable */ 335 Machine::AutoMutableStateDependency adep(m Parent);214 Machine::AutoMutableStateDependency adep(m->pMachine); 336 215 if (FAILED(adep.rc())) return adep.rc(); 337 216 338 217 AutoWriteLock alock(this); 339 218 340 if (m Data->mEnabled != aEnabled)219 if (m->bd->fEnabled != aEnabled) 341 220 { 342 221 if (aEnabled && 343 m Data->mPath.isEmpty())222 m->bd->strPath.isEmpty()) 344 223 return setError (E_INVALIDARG, 345 224 tr ("Cannot enable the parallel port %d " 346 225 "because the port path is empty or null"), 347 m Data->mSlot);348 349 m Data.backup();350 m Data->mEnabled = aEnabled;226 m->bd->ulSlot); 227 228 m->bd.backup(); 229 m->bd->fEnabled = aEnabled; 351 230 352 231 /* leave the lock before informing callbacks */ 353 232 alock.unlock(); 354 233 355 m Parent->onParallelPortChange (this);234 m->pMachine->onParallelPortChange (this); 356 235 } 357 236 … … 368 247 AutoReadLock alock(this); 369 248 370 *aSlot = m Data->mSlot;249 *aSlot = m->bd->ulSlot; 371 250 372 251 return S_OK; … … 382 261 AutoReadLock alock(this); 383 262 384 *aIRQ = m Data->mIRQ;263 *aIRQ = m->bd->ulIRQ; 385 264 386 265 return S_OK; … … 395 274 tr ("Invalid IRQ number of the parallel port %d: " 396 275 "%lu (must be in range [0, %lu])"), 397 m Data->mSlot, aIRQ, 255);276 m->bd->ulSlot, aIRQ, 255); 398 277 399 278 AutoCaller autoCaller(this); … … 401 280 402 281 /* the machine needs to be mutable */ 403 Machine::AutoMutableStateDependency adep(m Parent);282 Machine::AutoMutableStateDependency adep(m->pMachine); 404 283 if (FAILED(adep.rc())) return adep.rc(); 405 284 … … 409 288 bool emitChangeEvent = false; 410 289 411 if (m Data->mIRQ != aIRQ)412 { 413 m Data.backup();414 m Data->mIRQ = aIRQ;290 if (m->bd->ulIRQ != aIRQ) 291 { 292 m->bd.backup(); 293 m->bd->ulIRQ = aIRQ; 415 294 emitChangeEvent = true; 416 295 } … … 421 300 alock.unlock(); 422 301 423 m Parent->onParallelPortChange (this);302 m->pMachine->onParallelPortChange (this); 424 303 } 425 304 … … 436 315 AutoReadLock alock(this); 437 316 438 *aIOBase = m Data->mIOBase;317 *aIOBase = m->bd->ulIOBase; 439 318 440 319 return S_OK; … … 449 328 tr ("Invalid I/O port base address of the parallel port %d: " 450 329 "%lu (must be in range [0, 0x%X])"), 451 m Data->mSlot, aIOBase, 0, 0xFFFF);330 m->bd->ulSlot, aIOBase, 0, 0xFFFF); 452 331 453 332 AutoCaller autoCaller(this); … … 455 334 456 335 /* the machine needs to be mutable */ 457 Machine::AutoMutableStateDependency adep(m Parent);336 Machine::AutoMutableStateDependency adep(m->pMachine); 458 337 if (FAILED(adep.rc())) return adep.rc(); 459 338 … … 463 342 bool emitChangeEvent = false; 464 343 465 if (m Data->mIOBase != aIOBase)466 { 467 m Data.backup();468 m Data->mIOBase = aIOBase;344 if (m->bd->ulIOBase != aIOBase) 345 { 346 m->bd.backup(); 347 m->bd->ulIOBase = aIOBase; 469 348 emitChangeEvent = true; 470 349 } … … 475 354 alock.unlock(); 476 355 477 m Parent->onParallelPortChange (this);356 m->pMachine->onParallelPortChange (this); 478 357 } 479 358 … … 490 369 AutoReadLock alock(this); 491 370 492 m Data->mPath.cloneTo(aPath);371 m->bd->strPath.cloneTo(aPath); 493 372 494 373 return S_OK; … … 498 377 * Validates COMSETTER(Path) arguments. 499 378 */ 500 HRESULT ParallelPort::checkSetPath (CBSTR aPath)379 HRESULT ParallelPort::checkSetPath(const Utf8Str &str) 501 380 { 502 381 AssertReturn(isWriteLockOnCurrentThread(), E_FAIL); 503 382 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); 510 390 511 391 return S_OK; … … 518 398 519 399 /* the machine needs to be mutable */ 520 Machine::AutoMutableStateDependency adep(m Parent);400 Machine::AutoMutableStateDependency adep(m->pMachine); 521 401 if (FAILED(adep.rc())) return adep.rc(); 522 402 523 403 AutoWriteLock alock(this); 524 404 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); 532 409 if (FAILED(rc)) return rc; 533 410 534 m Data.backup();535 m Data->mPath = aPath;411 m->bd.backup(); 412 m->bd->strPath = str; 536 413 537 414 /* leave the lock before informing callbacks */ 538 415 alock.unlock(); 539 416 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 */ 434 HRESULT 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 */ 456 HRESULT 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 469 bool ParallelPort::isModified() 470 { 471 AutoWriteLock alock (this); 472 return m->bd.isBackedUp(); 473 } 474 475 bool ParallelPort::isReallyModified() 476 { 477 AutoWriteLock alock(this); 478 return m->bd.hasActualChanges(); 479 } 480 481 /** 482 * @note Locks this object for writing. 483 */ 484 bool 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 */ 509 void 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 */ 538 void 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 545 559 /* vi: set tabstop=4 shiftwidth=4 expandtab: */ -
trunk/src/VBox/Main/include/ParallelPortImpl.h
r24989 r25202 40 40 { 41 41 public: 42 43 struct Data44 {45 Data()46 : mSlot (0)47 , mEnabled (FALSE)48 , mIRQ (4)49 , mIOBase (0x378)50 {}51 52 bool operator== (const Data &that) const53 {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 69 42 VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT (ParallelPort) 70 43 … … 79 52 END_COM_MAP() 80 53 81 DECLARE_EMPTY_CTOR_DTOR (ParallelPort) 54 ParallelPort() {} 55 ~ParallelPort() {} 82 56 83 57 HRESULT FinalConstruct(); … … 106 80 HRESULT saveSettings(settings::ParallelPort &data); 107 81 108 bool isModified() { AutoWriteLock alock (this); return mData.isBackedUp(); }109 bool isReallyModified() { AutoWriteLock alock (this); return mData.hasActualChanges(); }82 bool isModified(); 83 bool isReallyModified(); 110 84 bool rollback(); 111 85 void commit(); 112 void copyFrom 86 void copyFrom(ParallelPort *aThat); 113 87 114 88 // public methods for internal purposes only … … 120 94 private: 121 95 122 HRESULT checkSetPath (CBSTR aPath);96 HRESULT checkSetPath(const Utf8Str &str); 123 97 124 const ComObjPtr<Machine, ComWeakRef> mParent; 125 const ComObjPtr<ParallelPort> mPeer; 126 127 Backupable<Data> mData; 98 struct Data; 99 Data *m; 128 100 }; 129 101
Note:
See TracChangeset
for help on using the changeset viewer.