Refactoring background task support

Discussion area about developing or extending OGRE, adding plugins for it or building applications on it. No newbie questions please, use the Help forum for that.
Post Reply
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19269
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Refactoring background task support

Post by sinbad »

Some of you might have noticed me noodling around in trunk regarding the threading support; here's just a quick note about the why's & how's:

Obviously I intend to support background loading of pages with the new paging component. However, these pages are not resources, and as such they wouldn't fit into the existing background loading idioms. I also want to support background processing of several things in the new terrain component (such as calculating normal/shadow/horizon maps, and updating height delta calculations), so I needed a more general way of queueing tasks for background processing. I also wasn't happy about having a separate thread for background loading and doing other things like this - I really just wanted a fixed pool of threads, and have a queue of tasks that they could pick off as and when they had time.

So, I added the WorkQueue class which allows me to do this. It's not domain-specific, instead it is a general background request/response queue, with a concept of 'channels' for categorising domains of interest (resource, paging, terrain, etc). There is one instance of this class in Root which will control all of Ogre's background processing, for any purpose, with a set of reserved channels. Users can push requests on to the queue too so long as they use their own channels. Request and response handlers can be plugged in to provide the code to implement the behaviour both in the background thread and dealing with the response in the main thread. All the data required to be passed between the background and main threads is encapsulated in an Any(), so you can pass whatever you like (for flexibility, passing by value wherever possible is best).

Users could also instantiate their own instance of WorkQueue if they wanted, although they wouldn't be able to share the same thread pool that way.

I'm almost done getting ResourceBackgroundQueue to use this centralised queue instead, and it seems to be working fine. It makes ResourceBackgroundQueue a lot simpler since it delegates all the complicated stuff to WorkQueue, and at the same time is a good example of how to use it with your own code.

My hope is this will provide more scope in future for threading more processes in Ogre more easily, with a fixed pool of multipurpose hardware threads. Right now though my focus is on paging and terrain.
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19269
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Re: Refactoring background task support

Post by sinbad »

I'm committing this now. I've tested it with my background loading tests and all seems to be well, but let me know if it causes you any problems. To get more information on what is going on in each thread, call LogManager::getSingleton().setLogDetail(LL_BOREME).

I also forgot to mention, I'm still using Boost for threading for simplicity. I may add the option to use other threading libs later but that's not my top priority.
User avatar
Chris Jones
Lich
Posts: 1742
Joined: Tue Apr 05, 2005 1:11 pm
Location: Gosport, South England
x 1

Re: Refactoring background task support

Post by Chris Jones »

Will it be possible for the application or game engine to be told by ogre that a task has been added so that it can manage all of its own threads? For example, in OGE the engine itself manages all of its threads (such as creating 1 thread per logical processor). These threads should be reused by the engine as well as other libraries rather than each library managing its own internal thread pools.

So can this new approach to threading in ogre be overriden? such as through a callback or listener?
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19269
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Re: Refactoring background task support

Post by sinbad »

You can already configure the number of threads (and reduce it to 0 if you want). The main issue of course is synchronisation - really you want your worker threads to suspend if there's nothing for them to do, but you can't have your own threads wait on both my sync condition and your own.

I can add a listener interface to the queue which calls back in the main thread when a request is added. You would then use this to trigger your own notify() call on your sync condition so that all of your wait conditions are unified. You would need to decide which queue you should be looking at though when being woken up - it's things like that which made me centralise things for us.

In practice, it might be easier to use the single queue for everything, then you know what your threads have to be doing when they wake up. So perhaps either use our queue, or as part of the listener interface I can include a flag which means 'don't add to our own queue'. Then when you process the items from your external queue, you feed them back into our queue for processing?
User avatar
iloseall
Gremlin
Posts: 156
Joined: Sun Sep 14, 2003 3:54 am
Location: Beijing China
Contact:

Re: Refactoring background task support

Post by iloseall »

sinbad wrote:So perhaps either use our queue, or as part of the listener interface I can include a flag which means 'don't add to our own queue'. Then when you process the items from your external queue, you feed them back into our queue for processing?
May we make a set of interface for WorkQueue and other thing about thread?
Sinbad 's code as default implement,Ogre's Users can use they external queue to replace this when they want.
User avatar
Chris Jones
Lich
Posts: 1742
Joined: Tue Apr 05, 2005 1:11 pm
Location: Gosport, South England
x 1

Re: Refactoring background task support

Post by Chris Jones »

May we make a set of interface for WorkQueue and other thing about thread?
Sinbad 's code as default implement,Ogre's Users can use they external queue to replace this when they want.
So we could supply our own implementation to be used? That does sound easier and more flexible than having any kind of listener/callback. Would that fit in easily with the current design?
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19269
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Re: Refactoring background task support

Post by sinbad »

Yes, WorkQueue is fully derivable if you need to, but I was concerned that would be less flexible for an external user than a listener, because by deriving from the WorkQueue you get certain default assumptions about the way things are processed.

Another option is to refactor WorkQueue into 2 classes, WorkQueue (interface) and DefaultWorkQueue (implementation), and let the user replace the default one in Root with another one. Again though, I don't know if that's more constraining than a Listener or not, because the more abstract the interface is, the more work it is to implement an alternative, but the more default implementation I put in WorkQueue to make that easier, the more complex it is to override. A Listener has the advantage of being able to short-circuit that to a degree.

I guess doing both is possible, but that would again require give any alternative implementation something extra to worry about (firing the listeners).

Thoughts welcome.
User avatar
Chris Jones
Lich
Posts: 1742
Joined: Tue Apr 05, 2005 1:11 pm
Location: Gosport, South England
x 1

Re: Refactoring background task support

Post by Chris Jones »

Another option is to refactor WorkQueue into 2 classes, WorkQueue (interface) and DefaultWorkQueue (implementation), and let the user replace the default one in Root with another one. Again though, I don't know if that's more constraining than a Listener or not, because the more abstract the interface is, the more work it is to implement an alternative, but the more default implementation I put in WorkQueue to make that easier, the more complex it is to override. A Listener has the advantage of being able to short-circuit that to a degree.
If you split it into two classes, then that would give both options when subclassing it. You could either subclass the WorkQueue and write the entire implementation or subclass the DefaultWorkQueue and modify its behaviour. Would that work well?
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19269
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Re: Refactoring background task support

Post by sinbad »

Probably yeah - I guess you're the one to answer that best though! If you think it'll work well in your case I'll do it.
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19269
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Re: Refactoring background task support

Post by sinbad »

Well, I've done it anyway, you can now subclass WorkQueue (interface only) or DefaultWorkQueue (default implementation) and tell Root to use yours instead via Root::setWorkQueue. Hope that works for you!
User avatar
cdleonard
Goblin
Posts: 266
Joined: Thu May 31, 2007 9:45 am

Re: Refactoring background task support

Post by cdleonard »

I recently tried to build Ogre with OGRE_THREAD_SUPPORT=1 on windows and the WorkQueue fails to initialise with OpenGL (works with Direct3D though). During initialization a lot of threads start up and they all call RenderSystem::registerThread at the same time. This breaks in wglShareLists; returning a message of "The requested resource is already in use". My guess is that this refers to the context being "current" on another thread; a rather ugly race condition.

Has anyone else tried OpenGL on Windows with this new code? System is windows XP; ATI and a quad core Athlon cpu (so there's plenty of room for threading bugs to manifest).
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19269
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Re: Refactoring background task support

Post by sinbad »

I did test in GL in Windows (OGRE_THREAD_SUPPORT=2) but didn't hit this problem, but I can see the potential for it. The reason is that we now start the number of worker threads to match the hardware support, so it's probably starting 4 on your machine, with the added potential for race conditions that brings. Previously there was only ever 1 additional thread.

I've separately mutexed the registerThread() method on GL, please give that a try. I still couldn't recreate the problem but I think it will fix yours.
User avatar
cdleonard
Goblin
Posts: 266
Joined: Thu May 31, 2007 9:45 am

Re: Refactoring background task support

Post by cdleonard »

sinbad wrote:I've separately mutexed the registerThread() method on GL, please give that a try. I still couldn't recreate the problem but I think it will fix yours.
It works OK now.
User avatar
_tommo_
Gnoll
Posts: 677
Joined: Tue Sep 19, 2006 6:09 pm
x 5
Contact:

Re: Refactoring background task support

Post by _tommo_ »

I tried the last Ogre from SVN, and i get 1154 linker errors because of worker-related methods... they are never found.

There's something other we must link to use the new ogre? :?

EDIT: Stupid me, i didn't run again CMake after the update... i didn't think at the addtional *.cpp files :D Never mind!
OverMindGames Blog
IndieVault.it: Il nuovo portale italiano su Game Dev & Indie Games
User avatar
xavier
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 9481
Joined: Fri Feb 18, 2005 2:03 am
Location: Dublin, CA, US
x 22

Re: Refactoring background task support

Post by xavier »

Why not leverage Thread Building Blocks for cross-platform thread and task management that you don't have to create or maintain? Apparently it builds on all of the platforms Ogre supports and it's GPLv2 with runtime exception, so should be consistent with Ogre's license.
Do you need help? What have you tried?

Image

Angels can fly because they take themselves lightly.
User avatar
:wumpus:
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 3067
Joined: Tue Feb 10, 2004 12:53 pm
Location: The Netherlands
x 1

Re: Refactoring background task support

Post by :wumpus: »

xavier wrote:Why not leverage Thread Building Blocks for cross-platform thread and task management that you don't have to create or maintain? Apparently it builds on all of the platforms Ogre supports and it's GPLv2 with runtime exception, so should be consistent with Ogre's license.
Oops, I never knew that TBB also did a low level thread abstraction, only the high-level stuff above it (hence my reply in the other topic)

Seems like a majorly useful library though. I don't have the knowledge of the subject matter at the moment to comment whether it fits in Ogre.
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19269
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Re: Refactoring background task support

Post by sinbad »

xavier wrote:Why not leverage Thread Building Blocks for cross-platform thread and task management that you don't have to create or maintain? Apparently it builds on all of the platforms Ogre supports and it's GPLv2 with runtime exception, so should be consistent with Ogre's license.
Mostly because I'm still wary of relying on TBB's higher-level structures, and the lower-level structures are the same as Boost's anyway. And Boost's will be in the C++ standard soon.

The reason I'm still a little nervous of TBB is that it's maintained by one company, who also control a compiler toolset, and who make parallel hardware architectures which this library targets. I know it's actually not a practical issue right now, and that the open source model should prevent any future issues, but still, that sort of direct self-interest makes me a little wary of hitching my wagon to it long-term. The GPL + runtime exception also makes even more people uncomfortable than the LGPL does, based on the people I've spoken to, and I could do nothing to amortise that for people worried about it except telling them to buy a commercial license from Intel.

Doing the task management this way with the low-level (trickier) stuff reused from Boost was IMO a better option. I'd be fine with using TBB in my own projects but I have a few too many qualms to force every Ogre user to use it, unlike Boost which I have no qualms about (company-independent, easier license).
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179
Contact:

Re: Refactoring background task support

Post by jacmoe »

Ratcliff (who had a very enjoyable rant about TBB here :) ) wrote an alternative solution called JobSwarm.
He was not keen on TBBs license, to put it mildly. I suggest checking it out. It's at http://sourceforge.net/projects/jobswarm/. :wink:
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
Post Reply