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