Jump to content
  • Advertisement
Sign in to follow this  
Hybrid666

Thread synchronisation question

This topic is 2643 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

I'm trying to figure out the best approach to solve a problem I'm having waiting for a group of 'tasks' to finish.

I have a task based model where N worker threads consume tasks added to a task list.

I'm trying to add sync points into the task list, so i can wait for a group of tasks to complete. i.e.

...
AddTask
s = AddSyncPoint
AddTask
AddTask
RemoveSyncPoint( s )
AddTask
...

then later on, i can
WaitForSyncPoint( s )

which will wait until those 2 tasks between the sync markers are processed.

I thought about using a semaphore, but I can't quite figure out how to make it work. The problem I'm having is that i (think i) want each task to be able to lock the sync object, and then reacquire the lock in the 'wait' function to say all is done. But because my tasks can be processed on any worker thread, I don't know how to make this approach work.

Thanks for any help, i'm a bit stuck, but am convinced I'm missing something obvious... my current best attempt is to use an atomic and a while( numActiveTasks ) { sleep( 0 ); } inside my wait function. I'm sure this is not good :)

Share this post


Link to post
Share on other sites
Advertisement
In C/C++ on Windows, I would use Events and WaitForMultipleObjects, with pthreads I'd use pthread_cond_t and pthread_cond_wait in a for loop.

You don't mention language or threading libraries but this sort of pattern works fine for me in a relatively lightweight job queue setup.

Share this post


Link to post
Share on other sites
Normally, you would have to wait for ALL work to be completed because of how a normal task-based threading is implemented. The reason is when you add a task to be processed, there isn't a guarantee on when it actually is processed compared to other tasks, or other work in progress. You could do a task_group mechanism where you create some code like this to watch certain tasks so when they are completed, you will know. This will prevent you from needing to wait for all work to complete --which could be other tasks that were started somewhere else in your code.

class task{
taskgroup* group;
public:

task(): group(0) {}
virtual ~task(){
if(group) group->refcounter-=1;// decrement the ref counter on destruction
}
friend taskgroup;
};
class taskgroup{
public:
taskgroup() : refcounter(0) {}
void addtasktogroup(task& t){
if(t.group) {// part of another group, being reassigned to this group
t.group->refcounter-=1;// decrement the other counter and assign this task to this group instead
t.group=this;
refcounter+=1;
}
atomic<unsigned int> refcounter;
};


And you would use it like this
task t1, t2, t3;
taskgroup g1, g2;
g1.addtasktogroup(t1);
AddTask(t1);
g2.addtasktogroup(t2);
g2.addtasktogroup(t3);
AddTask(t2);
AddTask(t3);
while(t1.refcounter !=0){
Sleep(1);// wait for taskgroup 1 to complete
}

Share this post


Link to post
Share on other sites
Thanks for the advice guys,

I wanted to avoid a sleep, or a per-task wait.. based on your feedback I don't think there is a nice way to achieve what I'm after.
I think I should stick to synchronising when the entire task queue is done :)

Thanks again!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!