Files
haiku-beta6/src/apps/expander/GenericThread.cpp
T

387 lines
6.8 KiB
C++
Raw Normal View History

// license: public domain
// authors: [email protected]
#include <GenericThread.h>
GenericThread::GenericThread(const char * a_thread_name, int32 a_priority, BMessage * a_message)
:
m_thread_data_store (a_message),
m_thread_id (spawn_thread (private_thread_function, a_thread_name, a_priority, this)),
m_execute_unit (create_sem(1, "m_execute_unit")),
m_quit_requested (false),
m_thread_is_paused (false)
{
if (m_thread_data_store == NULL)
m_thread_data_store = new BMessage();
}
GenericThread::~GenericThread()
{
kill_thread(m_thread_id);
delete_sem(m_execute_unit);
}
status_t
GenericThread::ThreadFunction (void)
{
status_t status = B_OK;
status = ThreadStartup(); // Subclass and override this function
if (status != B_OK)
{
ThreadStartupFailed (status);
return (status);
// is this the right thing to do?
}
while(1)
{
if (HasQuitBeenRequested())
{
status = ThreadShutdown(); // Subclass and override this function
if (status != B_OK)
{
ThreadShutdownFailed (status);
return (status);
// what do we do?
}
delete this; // destructor
}
BeginUnit();
status = ExecuteUnit(); // Subclass and override
if (status != B_OK)
ExecuteUnitFailed (status); // Subclass and override
EndUnit();
}
return (B_OK);
}
status_t
GenericThread::ThreadStartup (void)
{
// This function is virtual.
// Subclass and override this function.
return B_OK;
}
status_t
GenericThread::ExecuteUnit (void)
{
// This function is virtual.
// You would normally subclass and override this function
// as it will provide you with Pause and Quit functionality
// thanks to the unit management done by GenericThread::ThreadFunction()
return B_OK;
}
status_t
GenericThread::ThreadShutdown (void)
{
// This function is virtual.
// Subclass and override this function.
return B_OK;
}
void
GenericThread::ThreadStartupFailed (status_t a_status)
{
// This function is virtual.
// Subclass and override this function.
Quit();
}
void
GenericThread::ExecuteUnitFailed (status_t a_status)
{
// This function is virtual.
// Subclass and override this function.
Quit();
}
void
GenericThread::ThreadShutdownFailed (status_t a_status)
{
// This function is virtual.
// Subclass and override this function.
// (is this good default behaviour?)
}
status_t
GenericThread::Start (void)
{
status_t status = B_OK;
if (IsPaused())
{
status = release_sem (m_execute_unit);
if (status != B_OK)
return status;
m_thread_is_paused = false;
}
status = resume_thread (m_thread_id);
return status;
}
int32
GenericThread::private_thread_function (void * a_simple_thread_ptr)
{
status_t status = B_OK;
status = ((GenericThread *) a_simple_thread_ptr)-> ThreadFunction();
return (status);
}
BMessage *
GenericThread::GetDataStore (void)
{
return (m_thread_data_store);
}
void
GenericThread::SetDataStore (BMessage * a_message)
{
m_thread_data_store = a_message;
}
status_t
GenericThread::Pause (bool a_do_block, bigtime_t a_timeout)
{
status_t status = B_OK;
if (a_do_block)
status = acquire_sem(m_execute_unit);
// thread will wait on semaphore
else
status = acquire_sem_etc(m_execute_unit, 1, B_RELATIVE_TIMEOUT, a_timeout);
// thread will timeout
if (status == B_OK)
{
m_thread_is_paused = true;
return (B_OK);
}
return status;
}
void
GenericThread::Quit (void)
{
m_quit_requested = true;
}
bool
GenericThread::HasQuitBeenRequested (void)
{
return (m_quit_requested);
}
bool
GenericThread::IsPaused (void)
{
return (m_thread_is_paused);
}
status_t
GenericThread::Suspend (void)
{
return (suspend_thread(m_thread_id));
}
status_t
GenericThread::Resume (void)
{
release_sem(m_execute_unit); // to counteract Pause()
m_thread_is_paused = false;
return (resume_thread(m_thread_id)); // to counteract Suspend()
}
status_t
GenericThread::Kill (void)
{
return (kill_thread(m_thread_id));
}
void
GenericThread::ExitWithReturnValue (status_t a_return_value)
{
exit_thread(a_return_value);
}
status_t
GenericThread::SetExitCallback (void (*a_callback)(void*), void * a_data)
{
return (on_exit_thread(a_callback, a_data));
}
status_t
GenericThread::WaitForThread (status_t * a_exit_value)
{
return (wait_for_thread(m_thread_id, a_exit_value));
}
status_t
GenericThread::Rename (char * a_name)
{
return (rename_thread(m_thread_id, a_name));
}
status_t
GenericThread::SendData (int32 a_code, void * a_buffer, size_t a_buffer_size)
{
return (send_data(m_thread_id, a_code, a_buffer, a_buffer_size));
}
int32
GenericThread::ReceiveData (thread_id * a_sender, void * a_buffer, size_t a_buffer_size)
{
return (receive_data(a_sender, a_buffer, a_buffer_size));
}
bool
GenericThread::HasData (void)
{
return (has_data(m_thread_id));
}
status_t
GenericThread::SetPriority (int32 a_new_priority)
{
return (set_thread_priority(m_thread_id, a_new_priority));
}
void
GenericThread::Snooze (bigtime_t a_microseconds)
{
Suspend();
snooze(a_microseconds);
Resume();
}
void
GenericThread::SnoozeUntil (bigtime_t a_microseconds, int a_timebase)
{
Suspend();
snooze_until(a_microseconds, a_timebase);
Resume();
}
status_t
GenericThread::GetInfo (thread_info * a_thread_info)
{
return (get_thread_info(m_thread_id, a_thread_info));
}
thread_id
GenericThread::GetThread (void)
{
thread_info t_thread_info;
GetInfo (& t_thread_info);
return (t_thread_info.thread);
}
team_id
GenericThread::GetTeam (void)
{
thread_info t_thread_info;
GetInfo (& t_thread_info);
return (t_thread_info.team);
}
char *
GenericThread::GetName (void)
{
thread_info t_thread_info;
GetInfo (& t_thread_info);
return (t_thread_info.name);
}
thread_state
GenericThread::GetState (void)
{
thread_info t_thread_info;
GetInfo (& t_thread_info);
return (t_thread_info.state);
}
sem_id
GenericThread::GetSemaphore (void)
{
thread_info t_thread_info;
GetInfo (& t_thread_info);
return (t_thread_info.sem);
}
int32
GenericThread::GetPriority (void)
{
thread_info t_thread_info;
GetInfo (& t_thread_info);
return (t_thread_info.priority);
}
bigtime_t
GenericThread::GetUserTime (void)
{
thread_info t_thread_info;
GetInfo (& t_thread_info);
return (t_thread_info.user_time);
}
bigtime_t
GenericThread::GetKernelTime (void)
{
thread_info t_thread_info;
GetInfo (& t_thread_info);
return (t_thread_info.kernel_time);
}
void *
GenericThread::GetStackBase (void)
{
thread_info t_thread_info;
GetInfo (& t_thread_info);
return (t_thread_info.stack_base);
}
void *
GenericThread::GetStackEnd (void)
{
thread_info t_thread_info;
GetInfo (& t_thread_info);
return (t_thread_info.stack_end);
}
void
GenericThread::BeginUnit (void)
{
acquire_sem(m_execute_unit); // thread can not be paused until it releases semaphore
}
void
GenericThread::EndUnit (void)
{
release_sem(m_execute_unit); // thread can now be paused
}