13294d07bSStephan Aßmus // UpdateQueue.cpp 23294d07bSStephan Aßmus 33294d07bSStephan Aßmus #include <new> 43294d07bSStephan Aßmus #include <stdio.h> 5f6939eb1SStephan Aßmus #include <string.h> 63294d07bSStephan Aßmus 73294d07bSStephan Aßmus #include "HWInterface.h" 83294d07bSStephan Aßmus 93294d07bSStephan Aßmus #include "UpdateQueue.h" 103294d07bSStephan Aßmus 113294d07bSStephan Aßmus // constructor 123294d07bSStephan Aßmus UpdateQueue::UpdateQueue(HWInterface* interface) 13f38c001eSMarcus Overhagen : BLocker("AppServer_UpdateQueue"), 14f38c001eSMarcus Overhagen fInterface(interface), 153294d07bSStephan Aßmus fUpdateRegion(), 163294d07bSStephan Aßmus fUpdateExecutor(-1), 173294d07bSStephan Aßmus fThreadControl(-1), 183294d07bSStephan Aßmus fStatus(B_ERROR) 193294d07bSStephan Aßmus { 203294d07bSStephan Aßmus fThreadControl = create_sem(0, "update queue control"); 213294d07bSStephan Aßmus if (fThreadControl >= B_OK) 223294d07bSStephan Aßmus fStatus = B_OK; 233294d07bSStephan Aßmus else 243294d07bSStephan Aßmus fStatus = fThreadControl; 253294d07bSStephan Aßmus if (fStatus == B_OK) { 263294d07bSStephan Aßmus fUpdateExecutor = spawn_thread(_execute_updates_, "update queue runner", 273294d07bSStephan Aßmus B_NORMAL_PRIORITY, this); 283294d07bSStephan Aßmus if (fUpdateExecutor >= B_OK) { 293294d07bSStephan Aßmus fStatus = B_OK; 303294d07bSStephan Aßmus resume_thread(fUpdateExecutor); 313294d07bSStephan Aßmus } else 323294d07bSStephan Aßmus fStatus = fUpdateExecutor; 333294d07bSStephan Aßmus } 343294d07bSStephan Aßmus } 353294d07bSStephan Aßmus 363294d07bSStephan Aßmus // destructor 373294d07bSStephan Aßmus UpdateQueue::~UpdateQueue() 383294d07bSStephan Aßmus { 393294d07bSStephan Aßmus if (delete_sem(fThreadControl) == B_OK) 403294d07bSStephan Aßmus wait_for_thread(fUpdateExecutor, &fUpdateExecutor); 413294d07bSStephan Aßmus } 423294d07bSStephan Aßmus 433294d07bSStephan Aßmus // InitCheck 443294d07bSStephan Aßmus status_t 453294d07bSStephan Aßmus UpdateQueue::InitCheck() 463294d07bSStephan Aßmus { 473294d07bSStephan Aßmus return fStatus; 483294d07bSStephan Aßmus } 493294d07bSStephan Aßmus 503294d07bSStephan Aßmus // AddRect 513294d07bSStephan Aßmus void 523294d07bSStephan Aßmus UpdateQueue::AddRect(const BRect& rect) 533294d07bSStephan Aßmus { 5453115c99SStephan Aßmus // Lock(); 55f6939eb1SStephan Aßmus //printf("UpdateQueue::AddRect()\n"); 5674b3612aSStephan Aßmus // NOTE: The access to fUpdateRegion 5774b3612aSStephan Aßmus // is protected by the HWInterface lock. 5874b3612aSStephan Aßmus // When trying to access the fUpdateRegion, 5974b3612aSStephan Aßmus // our thread will first try to lock the 6074b3612aSStephan Aßmus // HWInterface, while on the other hand 6174b3612aSStephan Aßmus // HWInterface will always be locked when 6274b3612aSStephan Aßmus // it calls AddRect(). 633294d07bSStephan Aßmus fUpdateRegion.Include(rect); 6474b3612aSStephan Aßmus // _Reschedule(); 6553115c99SStephan Aßmus // Unlock(); 663294d07bSStephan Aßmus } 673294d07bSStephan Aßmus 683294d07bSStephan Aßmus // _execute_updates_ 693294d07bSStephan Aßmus int32 703294d07bSStephan Aßmus UpdateQueue::_execute_updates_(void* cookie) 713294d07bSStephan Aßmus { 723294d07bSStephan Aßmus UpdateQueue *gc = (UpdateQueue*)cookie; 733294d07bSStephan Aßmus return gc->_ExecuteUpdates(); 743294d07bSStephan Aßmus } 753294d07bSStephan Aßmus 763294d07bSStephan Aßmus // _ExecuteUpdates 773294d07bSStephan Aßmus int32 783294d07bSStephan Aßmus UpdateQueue::_ExecuteUpdates() 793294d07bSStephan Aßmus { 803294d07bSStephan Aßmus bool running = true; 813294d07bSStephan Aßmus while (running) { 823294d07bSStephan Aßmus status_t err = acquire_sem_etc(fThreadControl, 1, B_RELATIVE_TIMEOUT, 83f6939eb1SStephan Aßmus 20000); 843294d07bSStephan Aßmus switch (err) { 853294d07bSStephan Aßmus case B_OK: 863294d07bSStephan Aßmus case B_TIMED_OUT: 873294d07bSStephan Aßmus // execute updates 88*2cfe93e7SStephan Aßmus if (fInterface->LockParallelAccess()) { 893294d07bSStephan Aßmus int32 count = fUpdateRegion.CountRects(); 90f6939eb1SStephan Aßmus if (count > 0) { 913294d07bSStephan Aßmus for (int32 i = 0; i < count; i++) { 923294d07bSStephan Aßmus fInterface->CopyBackToFront(fUpdateRegion.RectAt(i)); 933294d07bSStephan Aßmus } 943294d07bSStephan Aßmus fUpdateRegion.MakeEmpty(); 95f6939eb1SStephan Aßmus } 96*2cfe93e7SStephan Aßmus fInterface->UnlockParallelAccess(); 973294d07bSStephan Aßmus } 983294d07bSStephan Aßmus break; 993294d07bSStephan Aßmus case B_BAD_SEM_ID: 1003294d07bSStephan Aßmus running = false; 1013294d07bSStephan Aßmus break; 1023294d07bSStephan Aßmus default: 103f6939eb1SStephan Aßmus printf("other error: %s\n", strerror(err)); 10474b3612aSStephan Aßmus //running = false; 105f6939eb1SStephan Aßmus snooze(20000); 1063294d07bSStephan Aßmus break; 1073294d07bSStephan Aßmus } 1083294d07bSStephan Aßmus } 1093294d07bSStephan Aßmus return 0; 1103294d07bSStephan Aßmus } 1113294d07bSStephan Aßmus 1123294d07bSStephan Aßmus // _Reschedule 1133294d07bSStephan Aßmus // 1143294d07bSStephan Aßmus // PRE: The object must be locked. 1153294d07bSStephan Aßmus void 1163294d07bSStephan Aßmus UpdateQueue::_Reschedule() 1173294d07bSStephan Aßmus { 11874b3612aSStephan Aßmus // TODO: _Reschedule() is supposed to cause the 11974b3612aSStephan Aßmus // immediate wake up of the update thread, but 12074b3612aSStephan Aßmus // the HWInterface is still locked when we get here. 12174b3612aSStephan Aßmus // Somehow this causes a deadlock, but I don't 12274b3612aSStephan Aßmus // see why yet... 1233294d07bSStephan Aßmus if (fStatus == B_OK) { 1243294d07bSStephan Aßmus release_sem(fThreadControl); 1253294d07bSStephan Aßmus } 1263294d07bSStephan Aßmus } 1273294d07bSStephan Aßmus 128