[haiku-development] Re: Creating a new thread
- From: Joseph Groover <looncraz@xxxxxxxxxxx>
- To: haiku-development@xxxxxxxxxxxxx
- Date: Sat, 05 May 2012 11:11:34 -0500
On 5/5/2012 07:40, David Rawson Couzelis wrote:
My Haiku application will download information from the Internet. To
prevent the GUI from locking up I need to do the downloading in a
separate thread. (correct?)
I think I need to create a subclass of BLooper and override the "Run"
method. To control it, I send it messages.
Is a BLooper subclass the best way to make a new thread by using the
Haiku API?
Thank you.
The best way is with spawn_thread and resume_thread:
I haven't tested this code, but it'll probably work (barring the
occassional tyypo...)
class ObjectWithThread{
public:
ObjectWithThread()
:
fThreadID(-1)
~ObjectWithThread()
{
if (fThread >= 0)
kill_thread(fThread); // can cause
problems, but that is another story
}
// actual thread function:
static status_t Thread(void * _pointer)
{
// do some work, case _pointer to an object you need
// for simplicity's sake, I normally do this:
((ObjectWithThread*)_pointer)->ThreadFunction();
return B_OK;
}
// because threads are static functions, the can't access
members of the
// object directly, so I normally just have the thread call
into the object
void ThreadFunction()
{
// do some work, you can access all members of the
object normally
}
// To create the thread:
void SomeCallYouWantToBeAsync()
{
// you will want to do some locking for while
the thread is running
// if the thread will not persist (in which
case you should use a semaphore
// to direct activity in the thread...
fThread = spawn_thread(&Thread,
"SuperDuperFancyThread", B_LOW_PRIORITY, this);
// The last argument, 'this', is the pointer
given to the static Thread function.
// Your thread is NOT running, yet.
if (fThread >= 0) // 0 is technically valid -
but would be used up in the kernel...
resume_thread(fThread);
// the thread is now running and will be
scheduled to perform its work now
// Any work you do here will occur while
the thread is running, and locking
// conflicts should be taken into account
// basically: don't hold a lock the
ThreadFunction uses and then wait for the
// thread to complete... that would freeze
both the app's thread and your
// SuperDuperFancyThread... which would not
be cool...
}
private:
thread_id fThread; // member variable
};
In the above quick-n-dirty example, the thread will exit after doing
whatever it is to do, I've found the easiest way to keep a thread
hanging around with as little issues as possible dealing with send_data
and others is as follows:
Create a member variable BLocker fSemaphore, then make the following
changes:
In the constructor of the object, spawn and resume the thread.
In SomeCallYouWantToBeAsync() just do the following:
{
// prepare for allowing your ThreadFunction to know what its next
task is...
fSemaphore.Unlock();
// the thread will be trying to gain the lock, and will safely
wait until it has it before
// doing any more work.
}
ThreadFunction()
{
while(fSemaphore.Lock(){
// do your work!
// I normally make a list of the argument to
SomeCallYouWantToBeAsync
// and have a sub-loop iterate through each of them here so
you get all
// the work done every time...
// the semaphore trick can, sometimes, stall because two
threads call
// fSemaphore.Unlock() at the same time, you will want to
protect that
// with another BLocker (which is just a semaphore in
sheep's clothing).
}
}
Good luck!
I'm sure someone will tell you my way is bad ;-) We all do things a
little differently ;-)
--The loon
Other related posts: