You are not logged in.

#1 2007-11-27 02:52:06

tntcoda
Member
Registered: 2007-07-24
Posts: 115

C++ Threading

Hi,

Im after some help with boost.threads, I have a vector/queue that the main application thread will add/remove tasks to, then 4 threads that i spawn will check that vector say every second or so for a new task, if there is something in the vector 1 of the 4 threads will take the task and process it, all the other threads will sleep in the mean time.

Is that sort of thing possible? Having read around it would seem i have to lock access with mutex's and use conditions, but i really cant work out how to get a very basic multi-threaded design going in this context. And from when i have used multiple threads before i have found it pretty confusing getting a simple design up and running sad

Any chance someone has an example related to this? i.e having a queue that the main thread can add to and having child threads monitoring/acting/sleeping based on the queue.

If it helps at all, the program will be downloading on 4 separate sockets from the internet, hence a thread for each socket and a main application queue. I think this is the best approach?

Thanks for any advice,

Jack

Offline

#2 2007-11-27 03:20:40

Cerebral
Forum Fellow
From: Waterloo, ON, CA
Registered: 2005-04-08
Posts: 3,108
Website

Re: C++ Threading

While my program structure design abilities are lacking, and hence I won't comment on your proposed architecture, I can tell you that yes, you will need to mutex the queue.  I haven't looked at boost's threading system yet, but generally the easiest way to do this is to have a class wrap the queue, something like this (pseudo-coded since I don't know boost):

class QueueWrapper {
private:
    std::vector<MyClassName*> queue;
    boost::mutexOfSomeSort mutex;

public:
    QueueWrapper() { }
    ~QueueWrapper() { }

    MyClassName* getNext() { 
        mutex.acquire();
        MyClassName* retVal = 0;
        if (!queue.empty()) {
            retVal = queue.back();
            queue.pop_back();
        }
        mutex.release();
        return retVal;
    }
 
    void addJob(MyClassName* newJob) {
        mutex.acquire();
        queue.insert(queue.front(), newJob);
        mutex.release();
    }
};

Then, your threads would use QueueWrapper::getNext() to get the next job - if that function returns NULL, there's no job to process, and the thread should sleep for a little bit, then check again.

Last edited by Cerebral (2007-11-27 03:23:03)

Offline

#3 2007-11-27 08:51:49

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: C++ Threading

Actually, rather than polling for valid items in a queue, this sounds like a job for a monitor! boost::conditional actually works perfectly for this

Here's pseudo code
http://en.wikipedia.org/wiki/Monitor_(s … _variables

I actually think I have a templated monitor class i've been kicking around somewhere, I can check tomorrow

Offline

#4 2007-11-27 12:17:29

Cerebral
Forum Fellow
From: Waterloo, ON, CA
Registered: 2005-04-08
Posts: 3,108
Website

Re: C++ Threading

I've been pwnt - that is a better architecture.  T.T

At least I was upfront about how much I suck at those things. XD

Offline

#5 2007-11-27 16:27:07

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: C++ Threading

Cerebral wrote:

I've been pwnt - that is a better architecture.

The monitor pattern is awesome, but it's not well known - in fact, I found out about it by reading through the bibliography links via the Boost.Threads docs - I apparently don't have the class I wrote, but it's almost trivial to make a "monitored queue":

template <typename T, int MaxSize> class monitored_queue {
    ...
    T* pop() {
        if(queue.size() == 0) non_empty_condition.wait();
        T* ret = queue.top();
        queue.pop();
        non_full_condition.signal();
        return ret;
    }
    ...
    void push(T* item) {
        if(queue.size() == MaxSize) non_full_condition.wait();
        queue.push(item);
        non_empty_condition.signal();
    }
    ...
}

Offline

#6 2007-11-27 17:01:14

Cerebral
Forum Fellow
From: Waterloo, ON, CA
Registered: 2005-04-08
Posts: 3,108
Website

Re: C++ Threading

hm - wouldn't you want to mutex those methods too?  I can see a race condition where two threads enter pop, check queue.size "simultaneously", find it to be 1, then both go in to pop the same item off the top.

Offline

#7 2007-11-27 18:36:17

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: C++ Threading

Cerebral wrote:

hm - wouldn't you want to mutex those methods too?  I can see a race condition where two threads enter pop, check queue.size "simultaneously", find it to be 1, then both go in to pop the same item off the top.

Yeah, probably. And because we're talking boost, you can just do:

void somefunc() {
    boost:scoped_lock lock(my_mutex);
    ....
    ....do nothing....
}

Ah, the wonders of guaranteed destruction. /me sighs

Offline

#8 2007-11-27 18:39:04

Cerebral
Forum Fellow
From: Waterloo, ON, CA
Registered: 2005-04-08
Posts: 3,108
Website

Re: C++ Threading

Heh, yeah, it's good stuff.  I haven't looked into boost's stuff, but at work we use very similar locking objects - it's just so much cleaner.  I'm glad to see that boost's threading library is at least that smart about it.

Offline

#9 2007-11-27 18:45:55

tntcoda
Member
Registered: 2007-07-24
Posts: 115

Re: C++ Threading

Thanks alot guys,  gives me something to work on now smile

Offline

Board footer

Powered by FluxBB