Redone from scratch because we don't have Dan Lee's code. Beta version. Testing is welcome. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7001 a95241bf-73f2-0310-859d-f6bbb57e9c96
387 lines
6.8 KiB
C++
387 lines
6.8 KiB
C++
// 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
|
|
}
|
|
|