[haiku-development] Re: Creating a new thread

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: