1/*
2 * Copyright (c) 1999-2000, Eric Moon.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions, and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions, and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * 3. The name of the author may not be used to endorse or promote products
17 *    derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31
32// BasicThread.h
33// based on ThreadPrimitive from the Be Newsletter
34//
35// HISTORY
36//   e.moon		12jul99: now in cortex namespace
37//   - The stop mechanism has changed a bit; it's now up to the
38//     run() implementation to indicate that it has completed by
39//     calling done().
40//
41//   e.moon		11may99: brought into the beDub support kit
42
43#ifndef __BasicThread_H__
44#define __BasicThread_H__
45
46#include <Debug.h>
47#include <KernelKit.h>
48#include <String.h>
49
50
51#include "cortex_defs.h"
52__BEGIN_CORTEX_NAMESPACE
53
54class BasicThread {
55
56protected:				// hooks
57	virtual void run()=0;
58
59public:					// ctor/dtor
60	virtual ~BasicThread() {
61
62		if(m_thread > 0) {
63			kill();
64		}
65	}
66
67	BasicThread(
68		int32 priority=B_LOW_PRIORITY,
69		const char* name=0,
70		bool killOnDelete=true) :
71
72		m_thread(-1),
73		m_priority(priority),
74		m_name(name ? name : "BasicThread [?]"),
75		m_running(false),
76		m_stopping(false) {}
77
78	bool running() const { return m_running; }
79	bool stopping() const { return m_stopping; }
80
81	thread_id thread() const { return m_thread; }
82	const char* name() const { return m_name.String(); }
83
84public:					// operations
85	status_t start() {
86
87		if(running())
88			return B_ERROR;
89
90		m_thread = spawn_thread(
91			&BasicThread::Run,
92			m_name.String(),
93			m_priority,
94			this);
95
96		status_t err = resume_thread(m_thread);
97		if(err == B_OK)
98			m_running = true;
99		return err;
100	}
101
102	// reworked 12jul99 e.moon
103	status_t stop(bool wait=true) {
104
105		if(!running())
106			return B_ERROR;
107
108		thread_id thread = m_thread; // +++++ is this safe?
109		if(thread <= 0)
110			return B_OK;
111
112		// signal stop
113		m_stopping = true;
114
115		if(wait) {
116			status_t ret;
117			while(wait_for_thread(thread, &ret) == B_INTERRUPTED) {
118				PRINT(("stopping thread %" B_PRId32 ": B_INTERRUPTED\n",
119					thread));
120			}
121		}
122
123		return B_OK;
124	}
125
126protected:					// internal methods
127
128	// Blunt force trauma.
129	// added 12jul99 e.moon
130	status_t kill() {
131		if(m_thread <= 0)
132			return B_ERROR;
133
134		kill_thread(m_thread);
135
136		m_thread = -1;
137		m_running = false;
138		m_stopping = false;
139		return B_OK;
140	}
141
142	// Call this method at the end of your run() implementation.
143	// added 12jul99 e.moon
144	void done() {
145		m_running = false;
146		m_stopping = false;
147		m_thread = -1;
148	}
149
150private:						// static impl. methods
151	static status_t Run(void* user) {
152
153		BasicThread* instance = static_cast<BasicThread*>(user);
154		instance->run();
155		return B_OK;
156	}
157
158private:						// impl members
159	thread_id		m_thread;
160	int32				m_priority;
161	BString			m_name;
162
163	bool					m_running;
164	bool					m_stopping;
165};
166
167__END_CORTEX_NAMESPACE
168#endif /* __BasicThread_H__ */
169