⛏️ index : haiku.git

/*
 * Copyright (c) 1999-2000, Eric Moon.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions, and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


// BasicThread.h
// based on ThreadPrimitive from the Be Newsletter
//
// HISTORY
//   e.moon		12jul99: now in cortex namespace
//   - The stop mechanism has changed a bit; it's now up to the
//     run() implementation to indicate that it has completed by
//     calling done().
//                    
//   e.moon		11may99: brought into the beDub support kit

#ifndef __BasicThread_H__
#define __BasicThread_H__

#include <Debug.h>
#include <KernelKit.h>
#include <String.h>


#include "cortex_defs.h"
__BEGIN_CORTEX_NAMESPACE

class BasicThread {

protected:				// hooks
	virtual void run()=0;

public:					// ctor/dtor
	virtual ~BasicThread() {

		if(m_thread > 0) {
			kill();
		}
	}
	
	BasicThread(
		int32 priority=B_LOW_PRIORITY,
		const char* name=0,
		bool killOnDelete=true) :
		
		m_thread(-1),
		m_priority(priority),
		m_name(name ? name : "BasicThread [?]"),
		m_running(false),
		m_stopping(false) {}
	
	bool running() const { return m_running; }
	bool stopping() const { return m_stopping; }
	
	thread_id thread() const { return m_thread; }
	const char* name() const { return m_name.String(); }
		
public:					// operations
	status_t start() {

		if(running())
			return B_ERROR;
			
		m_thread = spawn_thread(
			&BasicThread::Run,
			m_name.String(),
			m_priority,
			this);

		status_t err = resume_thread(m_thread);
		if(err == B_OK)
			m_running = true;
		return err;
	}

	// reworked 12jul99 e.moon
	status_t stop(bool wait=true) {

		if(!running())
			return B_ERROR;

		thread_id thread = m_thread; // +++++ is this safe?
		if(thread <= 0)
			return B_OK;

		// signal stop
		m_stopping = true;
		
		if(wait) {
			status_t ret;
			while(wait_for_thread(thread, &ret) == B_INTERRUPTED) {
				PRINT(("stopping thread %" B_PRId32 ": B_INTERRUPTED\n",
					thread));
			}
		}
		
		return B_OK;
	}

protected:					// internal methods	

	// Blunt force trauma.
	// added 12jul99 e.moon
	status_t kill() {
		if(m_thread <= 0)
			return B_ERROR;

		kill_thread(m_thread);
		
		m_thread = -1;
		m_running = false;
		m_stopping = false;
		return B_OK;
	}

	// Call this method at the end of your run() implementation.
	// added 12jul99 e.moon
	void done() {
		m_running = false;
		m_stopping = false;
		m_thread = -1;
	}

private:						// static impl. methods
	static status_t Run(void* user) {

		BasicThread* instance = static_cast<BasicThread*>(user);
		instance->run();
		return B_OK;
	}
	
private:						// impl members
	thread_id		m_thread;
	int32				m_priority;
	BString			m_name;

	bool					m_running;	
	bool					m_stopping;
};

__END_CORTEX_NAMESPACE
#endif /* __BasicThread_H__ */