1 // UpdateQueue.cpp 2 3 #include <new> 4 #include <stdio.h> 5 #include <string.h> 6 7 #include "HWInterface.h" 8 9 #include "UpdateQueue.h" 10 11 // constructor 12 UpdateQueue::UpdateQueue(HWInterface* interface) 13 : BLocker("AppServer_UpdateQueue"), 14 fInterface(interface), 15 fUpdateRegion(), 16 fUpdateExecutor(-1), 17 fThreadControl(-1), 18 fStatus(B_ERROR) 19 { 20 fThreadControl = create_sem(0, "update queue control"); 21 if (fThreadControl >= B_OK) 22 fStatus = B_OK; 23 else 24 fStatus = fThreadControl; 25 if (fStatus == B_OK) { 26 fUpdateExecutor = spawn_thread(_execute_updates_, "update queue runner", 27 B_NORMAL_PRIORITY, this); 28 if (fUpdateExecutor >= B_OK) { 29 fStatus = B_OK; 30 resume_thread(fUpdateExecutor); 31 } else 32 fStatus = fUpdateExecutor; 33 } 34 } 35 36 // destructor 37 UpdateQueue::~UpdateQueue() 38 { 39 if (delete_sem(fThreadControl) == B_OK) 40 wait_for_thread(fUpdateExecutor, &fUpdateExecutor); 41 } 42 43 // InitCheck 44 status_t 45 UpdateQueue::InitCheck() 46 { 47 return fStatus; 48 } 49 50 // AddRect 51 void 52 UpdateQueue::AddRect(const BRect& rect) 53 { 54 // Lock(); 55 //printf("UpdateQueue::AddRect()\n"); 56 // NOTE: The access to fUpdateRegion 57 // is protected by the HWInterface lock. 58 // When trying to access the fUpdateRegion, 59 // our thread will first try to lock the 60 // HWInterface, while on the other hand 61 // HWInterface will always be locked when 62 // it calls AddRect(). 63 fUpdateRegion.Include(rect); 64 // _Reschedule(); 65 // Unlock(); 66 } 67 68 // _execute_updates_ 69 int32 70 UpdateQueue::_execute_updates_(void* cookie) 71 { 72 UpdateQueue *gc = (UpdateQueue*)cookie; 73 return gc->_ExecuteUpdates(); 74 } 75 76 // _ExecuteUpdates 77 int32 78 UpdateQueue::_ExecuteUpdates() 79 { 80 bool running = true; 81 while (running) { 82 status_t err = acquire_sem_etc(fThreadControl, 1, B_RELATIVE_TIMEOUT, 83 20000); 84 switch (err) { 85 case B_OK: 86 case B_TIMED_OUT: 87 // execute updates 88 if (fInterface->ReadLock()) { 89 int32 count = fUpdateRegion.CountRects(); 90 if (count > 0) { 91 for (int32 i = 0; i < count; i++) { 92 fInterface->CopyBackToFront(fUpdateRegion.RectAt(i)); 93 } 94 fUpdateRegion.MakeEmpty(); 95 } 96 fInterface->ReadUnlock(); 97 } 98 break; 99 case B_BAD_SEM_ID: 100 running = false; 101 break; 102 default: 103 printf("other error: %s\n", strerror(err)); 104 //running = false; 105 snooze(20000); 106 break; 107 } 108 } 109 return 0; 110 } 111 112 // _Reschedule 113 // 114 // PRE: The object must be locked. 115 void 116 UpdateQueue::_Reschedule() 117 { 118 // TODO: _Reschedule() is supposed to cause the 119 // immediate wake up of the update thread, but 120 // the HWInterface is still locked when we get here. 121 // Somehow this causes a deadlock, but I don't 122 // see why yet... 123 if (fStatus == B_OK) { 124 release_sem(fThreadControl); 125 } 126 } 127 128