xref: /haiku/src/servers/app/drawing/UpdateQueue.cpp (revision 3294d07b156f3329d8c5839d297089ae84d5ffa7)
1*3294d07bSStephan Aßmus // UpdateQueue.cpp
2*3294d07bSStephan Aßmus 
3*3294d07bSStephan Aßmus #include <new>
4*3294d07bSStephan Aßmus #include <stdio.h>
5*3294d07bSStephan Aßmus 
6*3294d07bSStephan Aßmus #include "HWInterface.h"
7*3294d07bSStephan Aßmus 
8*3294d07bSStephan Aßmus #include "UpdateQueue.h"
9*3294d07bSStephan Aßmus 
10*3294d07bSStephan Aßmus // constructor
11*3294d07bSStephan Aßmus UpdateQueue::UpdateQueue(HWInterface* interface)
12*3294d07bSStephan Aßmus 	: fInterface(interface),
13*3294d07bSStephan Aßmus 	  fUpdateRegion(),
14*3294d07bSStephan Aßmus 	  fUpdateExecutor(-1),
15*3294d07bSStephan Aßmus 	  fThreadControl(-1),
16*3294d07bSStephan Aßmus 	  fStatus(B_ERROR)
17*3294d07bSStephan Aßmus 
18*3294d07bSStephan Aßmus {
19*3294d07bSStephan Aßmus 	fThreadControl = create_sem(0, "update queue control");
20*3294d07bSStephan Aßmus 	if (fThreadControl >= B_OK)
21*3294d07bSStephan Aßmus 		fStatus = B_OK;
22*3294d07bSStephan Aßmus 	else
23*3294d07bSStephan Aßmus 		fStatus = fThreadControl;
24*3294d07bSStephan Aßmus 	if (fStatus == B_OK) {
25*3294d07bSStephan Aßmus 		fUpdateExecutor = spawn_thread(_execute_updates_, "update queue runner",
26*3294d07bSStephan Aßmus 									   B_NORMAL_PRIORITY, this);
27*3294d07bSStephan Aßmus 		if (fUpdateExecutor >= B_OK) {
28*3294d07bSStephan Aßmus 			fStatus = B_OK;
29*3294d07bSStephan Aßmus 			resume_thread(fUpdateExecutor);
30*3294d07bSStephan Aßmus 		} else
31*3294d07bSStephan Aßmus 			fStatus = fUpdateExecutor;
32*3294d07bSStephan Aßmus 	}
33*3294d07bSStephan Aßmus }
34*3294d07bSStephan Aßmus 
35*3294d07bSStephan Aßmus // destructor
36*3294d07bSStephan Aßmus UpdateQueue::~UpdateQueue()
37*3294d07bSStephan Aßmus {
38*3294d07bSStephan Aßmus 	if (delete_sem(fThreadControl) == B_OK)
39*3294d07bSStephan Aßmus 		wait_for_thread(fUpdateExecutor, &fUpdateExecutor);
40*3294d07bSStephan Aßmus }
41*3294d07bSStephan Aßmus 
42*3294d07bSStephan Aßmus // InitCheck
43*3294d07bSStephan Aßmus status_t
44*3294d07bSStephan Aßmus UpdateQueue::InitCheck()
45*3294d07bSStephan Aßmus {
46*3294d07bSStephan Aßmus 	return fStatus;
47*3294d07bSStephan Aßmus }
48*3294d07bSStephan Aßmus 
49*3294d07bSStephan Aßmus // AddRect
50*3294d07bSStephan Aßmus void
51*3294d07bSStephan Aßmus UpdateQueue::AddRect(const BRect& rect)
52*3294d07bSStephan Aßmus {
53*3294d07bSStephan Aßmus 	Lock();
54*3294d07bSStephan Aßmus 	fUpdateRegion.Include(rect);
55*3294d07bSStephan Aßmus 	_Reschedule();
56*3294d07bSStephan Aßmus 	Unlock();
57*3294d07bSStephan Aßmus }
58*3294d07bSStephan Aßmus 
59*3294d07bSStephan Aßmus // _execute_updates_
60*3294d07bSStephan Aßmus int32
61*3294d07bSStephan Aßmus UpdateQueue::_execute_updates_(void* cookie)
62*3294d07bSStephan Aßmus {
63*3294d07bSStephan Aßmus 	UpdateQueue *gc = (UpdateQueue*)cookie;
64*3294d07bSStephan Aßmus 	return gc->_ExecuteUpdates();
65*3294d07bSStephan Aßmus }
66*3294d07bSStephan Aßmus 
67*3294d07bSStephan Aßmus // _ExecuteUpdates
68*3294d07bSStephan Aßmus int32
69*3294d07bSStephan Aßmus UpdateQueue::_ExecuteUpdates()
70*3294d07bSStephan Aßmus {
71*3294d07bSStephan Aßmus 	bool running = true;
72*3294d07bSStephan Aßmus 	while (running) {
73*3294d07bSStephan Aßmus 		status_t err = acquire_sem_etc(fThreadControl, 1, B_RELATIVE_TIMEOUT,
74*3294d07bSStephan Aßmus 									   40000);
75*3294d07bSStephan Aßmus 		switch (err) {
76*3294d07bSStephan Aßmus 			case B_OK:
77*3294d07bSStephan Aßmus 			case B_TIMED_OUT:
78*3294d07bSStephan Aßmus 				// execute updates
79*3294d07bSStephan Aßmus 				if (Lock()) {
80*3294d07bSStephan Aßmus //					if (fInterface->Lock()) {
81*3294d07bSStephan Aßmus 						int32 count = fUpdateRegion.CountRects();
82*3294d07bSStephan Aßmus 						for (int32 i = 0; i < count; i++) {
83*3294d07bSStephan Aßmus 							fInterface->CopyBackToFront(fUpdateRegion.RectAt(i));
84*3294d07bSStephan Aßmus 						}
85*3294d07bSStephan Aßmus //						fInterface->Unlock();
86*3294d07bSStephan Aßmus 						fUpdateRegion.MakeEmpty();
87*3294d07bSStephan Aßmus //					}
88*3294d07bSStephan Aßmus 					Unlock();
89*3294d07bSStephan Aßmus 				}
90*3294d07bSStephan Aßmus 				break;
91*3294d07bSStephan Aßmus 			case B_BAD_SEM_ID:
92*3294d07bSStephan Aßmus 				running = false;
93*3294d07bSStephan Aßmus 				break;
94*3294d07bSStephan Aßmus 			default:
95*3294d07bSStephan Aßmus 				break;
96*3294d07bSStephan Aßmus 		}
97*3294d07bSStephan Aßmus 	}
98*3294d07bSStephan Aßmus 	return 0;
99*3294d07bSStephan Aßmus }
100*3294d07bSStephan Aßmus 
101*3294d07bSStephan Aßmus // _Reschedule
102*3294d07bSStephan Aßmus //
103*3294d07bSStephan Aßmus // PRE: The object must be locked.
104*3294d07bSStephan Aßmus void
105*3294d07bSStephan Aßmus UpdateQueue::_Reschedule()
106*3294d07bSStephan Aßmus {
107*3294d07bSStephan Aßmus 	if (fStatus == B_OK) {
108*3294d07bSStephan Aßmus 		if (fUpdateRegion.Frame().IsValid())
109*3294d07bSStephan Aßmus 			release_sem(fThreadControl);
110*3294d07bSStephan Aßmus 	}
111*3294d07bSStephan Aßmus }
112*3294d07bSStephan Aßmus 
113