xref: /haiku/src/servers/app/drawing/UpdateQueue.cpp (revision 2cfe93e7804edb2817dba26ba9b908efbfa80b06)
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