xref: /haiku/src/apps/expander/GenericThread.cpp (revision 1294543de9ac0eff000eaea1b18368c36435d08e)
1 // license: public domain
2 // authors: jonas.sundstrom@kirilla.com
3 
4 #include "GenericThread.h"
5 
6 #include <string.h>
7 
8 GenericThread::GenericThread(const char * thread_name, int32 a_priority, BMessage * message)
9 	:
10 	fThreadDataStore(message),
11 	fThreadId(spawn_thread(private_thread_function, thread_name, a_priority, this)),
12 	fExecuteUnit(create_sem(1, "ExecuteUnit sem")),
13 	fQuitRequested(false),
14 	fThreadIsPaused(false)
15 {
16 	if (fThreadDataStore == NULL)
17 		fThreadDataStore	=	new BMessage();
18 }
19 
20 
21 GenericThread::~GenericThread()
22 {
23 	kill_thread(fThreadId);
24 
25 	delete_sem(fExecuteUnit);
26 }
27 
28 
29 status_t
30 GenericThread::ThreadFunction(void)
31 {
32 	status_t  status  =  B_OK;
33 
34 	status = ThreadStartup();	// Subclass and override this function
35 	if (status != B_OK)
36 	{
37 		ThreadStartupFailed(status);
38 		return (status);
39 		// is this the right thing to do?
40 	}
41 
42 	while (1)
43 	{
44 		if (HasQuitBeenRequested())
45 		{
46 			status = ThreadShutdown();	// Subclass and override this function
47 			if (status != B_OK)
48 			{
49 				ThreadShutdownFailed(status);
50 				return (status);
51 				// what do we do?
52 			}
53 
54 			delete this;		// destructor
55 		}
56 
57 		BeginUnit();
58 
59 		status = ExecuteUnit();	// Subclass and override
60 
61 		if (status != B_OK)
62 			ExecuteUnitFailed(status);  // Subclass and override
63 
64 		EndUnit();
65 	}
66 
67 	return (B_OK);
68 }
69 
70 
71 status_t
72 GenericThread::ThreadStartup(void)
73 {
74 	// This function is virtual.
75 	// Subclass and override this function.
76 
77 	return B_OK;
78 }
79 
80 
81 status_t
82 GenericThread::ExecuteUnit(void)
83 {
84 	// This function is virtual.
85 
86 	// You would normally subclass and override this function
87 	// as it will provide you with Pause and Quit functionality
88 	// thanks to the unit management done by GenericThread::ThreadFunction()
89 
90 	return B_OK;
91 }
92 
93 
94 status_t
95 GenericThread::ThreadShutdown(void)
96 {
97 	// This function is virtual.
98 	// Subclass and override this function.
99 
100 	return B_OK;
101 }
102 
103 
104 void
105 GenericThread::ThreadStartupFailed(status_t a_status)
106 {
107 	// This function is virtual.
108 	// Subclass and override this function.
109 
110 	Quit();
111 }
112 
113 
114 void
115 GenericThread::ExecuteUnitFailed(status_t a_status)
116 {
117 	// This function is virtual.
118 	// Subclass and override this function.
119 
120 	Quit();
121 }
122 
123 
124 void
125 GenericThread::ThreadShutdownFailed(status_t a_status)
126 {
127 	// This function is virtual.
128 	// Subclass and override this function.
129 
130 	// (is this good default behaviour?)
131 }
132 
133 
134 status_t
135 GenericThread::Start(void)
136 {
137 	status_t	status	=	B_OK;
138 
139 	if (IsPaused())
140 	{
141 		status	=	release_sem(fExecuteUnit);
142 		if (status != B_OK)
143 			return status;
144 
145 		fThreadIsPaused	=	false;
146 	}
147 
148 	status	=	resume_thread(fThreadId);
149 
150 	return status;
151 }
152 
153 
154 int32
155 GenericThread::private_thread_function(void * a_simple_thread_ptr)
156 {
157 	status_t	status	=	B_OK;
158 
159 	status	=	((GenericThread *) a_simple_thread_ptr)-> ThreadFunction();
160 
161 	return (status);
162 }
163 
164 
165 BMessage *
166 GenericThread::GetDataStore(void)
167 {
168 	return	(fThreadDataStore);
169 }
170 
171 
172 void
173 GenericThread::SetDataStore(BMessage * message)
174 {
175 	fThreadDataStore  =  message;
176 }
177 
178 
179 status_t
180 GenericThread::Pause(bool a_do_block, bigtime_t a_timeout)
181 {
182 	status_t	status	=	B_OK;
183 
184 	if (a_do_block)
185 		status	=	acquire_sem(fExecuteUnit);
186 	// thread will wait on semaphore
187 	else
188 		status	=	acquire_sem_etc(fExecuteUnit, 1, B_RELATIVE_TIMEOUT, a_timeout);
189 	// thread will timeout
190 
191 	if (status == B_OK)
192 	{
193 		fThreadIsPaused	=	true;
194 		return (B_OK);
195 	}
196 
197 	return status;
198 }
199 
200 
201 void
202 GenericThread::Quit(void)
203 {
204 	fQuitRequested	=	true;
205 }
206 
207 
208 bool
209 GenericThread::HasQuitBeenRequested(void)
210 {
211 	return (fQuitRequested);
212 }
213 
214 
215 bool
216 GenericThread::IsPaused(void)
217 {
218 	return (fThreadIsPaused);
219 }
220 
221 
222 status_t
223 GenericThread::Suspend(void)
224 {
225 	return (suspend_thread(fThreadId));
226 }
227 
228 
229 status_t
230 GenericThread::Resume(void)
231 {
232 	release_sem(fExecuteUnit);		// to counteract Pause()
233 	fThreadIsPaused	=	false;
234 
235 	return (resume_thread(fThreadId));	// to counteract Suspend()
236 }
237 
238 
239 status_t
240 GenericThread::Kill(void)
241 {
242 	return (kill_thread(fThreadId));
243 }
244 
245 
246 void
247 GenericThread::ExitWithReturnValue(status_t a_return_value)
248 {
249 	exit_thread(a_return_value);
250 }
251 
252 
253 status_t
254 GenericThread::SetExitCallback(void(*a_callback)(void*), void * a_data)
255 {
256 	return (on_exit_thread(a_callback, a_data));
257 }
258 
259 
260 status_t
261 GenericThread::WaitForThread(status_t * a_exit_value)
262 {
263 	return (wait_for_thread(fThreadId, a_exit_value));
264 }
265 
266 
267 status_t
268 GenericThread::Rename(char * a_name)
269 {
270 	return (rename_thread(fThreadId, a_name));
271 }
272 
273 
274 status_t
275 GenericThread::SendData(int32 a_code, void * a_buffer, size_t a_buffer_size)
276 {
277 	return (send_data(fThreadId, a_code, a_buffer, a_buffer_size));
278 }
279 
280 
281 int32
282 GenericThread::ReceiveData(thread_id * a_sender, void * a_buffer, size_t a_buffer_size)
283 {
284 	return (receive_data(a_sender, a_buffer, a_buffer_size));
285 }
286 
287 
288 bool
289 GenericThread::HasData(void)
290 {
291 	return (has_data(fThreadId));
292 }
293 
294 
295 status_t
296 GenericThread::SetPriority(int32 a_new_priority)
297 {
298 	return (set_thread_priority(fThreadId, a_new_priority));
299 }
300 
301 
302 void
303 GenericThread::Snooze(bigtime_t a_microseconds)
304 {
305 	Suspend();
306 	snooze(a_microseconds);
307 	Resume();
308 }
309 
310 
311 void
312 GenericThread::SnoozeUntil(bigtime_t a_microseconds, int a_timebase)
313 {
314 	Suspend();
315 	snooze_until(a_microseconds, a_timebase);
316 	Resume();
317 }
318 
319 
320 status_t
321 GenericThread::GetInfo(thread_info * thread_info)
322 {
323 	return (get_thread_info(fThreadId, thread_info));
324 }
325 
326 
327 thread_id
328 GenericThread::GetThread(void)
329 {
330 	thread_info	t_thread_info;
331 	GetInfo(& t_thread_info);
332 	return (t_thread_info.thread);
333 }
334 
335 
336 team_id
337 GenericThread::GetTeam(void)
338 {
339 	thread_info	t_thread_info;
340 	GetInfo(& t_thread_info);
341 	return (t_thread_info.team);
342 }
343 
344 
345 char *
346 GenericThread::GetName(void)
347 {
348 	thread_info	t_thread_info;
349 	GetInfo(& t_thread_info);
350 	return strdup(t_thread_info.name);
351 }
352 
353 
354 thread_state
355 GenericThread::GetState(void)
356 {
357 	thread_info	t_thread_info;
358 	GetInfo(& t_thread_info);
359 	return (t_thread_info.state);
360 }
361 
362 
363 sem_id
364 GenericThread::GetSemaphore(void)
365 {
366 	thread_info	t_thread_info;
367 	GetInfo(& t_thread_info);
368 	return (t_thread_info.sem);
369 }
370 
371 
372 int32
373 GenericThread::GetPriority(void)
374 {
375 	thread_info	t_thread_info;
376 	GetInfo(& t_thread_info);
377 	return (t_thread_info.priority);
378 }
379 
380 
381 bigtime_t
382 GenericThread::GetUserTime(void)
383 {
384 	thread_info	t_thread_info;
385 	GetInfo(& t_thread_info);
386 	return (t_thread_info.user_time);
387 }
388 
389 
390 bigtime_t
391 GenericThread::GetKernelTime(void)
392 {
393 	thread_info	t_thread_info;
394 	GetInfo(& t_thread_info);
395 	return (t_thread_info.kernel_time);
396 }
397 
398 
399 void *
400 GenericThread::GetStackBase(void)
401 {
402 	thread_info	t_thread_info;
403 	GetInfo(& t_thread_info);
404 	return (t_thread_info.stack_base);
405 }
406 
407 
408 void *
409 GenericThread::GetStackEnd(void)
410 {
411 	thread_info	t_thread_info;
412 	GetInfo(& t_thread_info);
413 	return (t_thread_info.stack_end);
414 }
415 
416 
417 void
418 GenericThread::BeginUnit(void)
419 {
420 	acquire_sem(fExecuteUnit); // thread can not be paused until it releases semaphore
421 }
422 
423 
424 void
425 GenericThread::EndUnit(void)
426 {
427 	release_sem(fExecuteUnit); // thread can now be paused
428 }
429 
430