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