Praetor summed this up pretty well. To respond individually to some of the points:
sparkprime wrote:So, for not much parallelism, we paid a high cost in terms of linear locking overhead
Bingo. Basically, I'm proposing a change because the existing approaches requires that if you enable threading in OGRE at all, too many classes need to become thread safe, which means a lot of locking regardless of how much parallel work you actually do, because the API is trying to make itself generally threadsafe in certain areas (mostly resource and the classes that uses).
Not only is inefficient, it makes the code complex and difficult to maintain, and it's very hard to describe accurately to the user as to what they can and can't do thread safely, which is where this comes from:
tp wrote:The documentation and information about how Ogre works with and without threading, what you can do about it and which parts of the library are thread safe: 5%. I mean, the best source of information are the patch notes where the different OGRE_THREAD_SUPPORT modes were published.
I completely agree. And this is one of the things I want to fix with this new mode, because not only is it simpler to implement, it's also a lot easier to explain and put a box around for users to grasp.
tp wrote:(Script parsing): My belief is that lots of people in the "thread to make the game work better" group (i.e. the first group I mentioned) are, at best, very concerned, and at worst, losing their faith, when they read something like this. It's really a pity, because these people might be interested...
As Praetor said, it's still possible to do the script parsing in the background, it's just that building the Materials etc can't be done there. I raised it because it's one of the trickier areas and hilights the difference between the two approaches - ie it's entirely data-driven and not about trying to make the entire API thread safe.
I've implemented several apps now where I've built Ogre with OGRE_THREAD_SUPPORT=0 and threaded I/O and other processing outside of that, in order to give the user an uninterrupted experience. The lack of locking in Ogre has also meant I've been able to get better FPS in those apps than if I'd used OGRE_THREAD_SUPPORT=1/2. I raised this because I'd like other people to be able to access that kind of flexibility more easily. You shouldn't assume that the change will somehow remove the ability to prevent hiccups when loading - it will continue to provide that ability, just slightly differently, with better overall performance if anything.
steven wrote:For me Ogre is just a library that I use hence I don't want that ogre creates threads I don't have control over.
If all libraries do the same (physics, Ai, network, etc) you end up with dozens of competing threads - and usually you can't set the cpu affinity of those.
We will allow that, and in fact we always have. There has always been the option to tell OGRE not start its own threads and for you to drive the background processes yourself, that won't change.
steven wrote:Hence I strongly hope that OGRE_THREAD_SUPPORT (==3) will come with an Ogre sample using an external workqueue / tasks / threads scheduler (or any name you want to call it). I think you will agree that a sample that load in the background terrain & assets and perhaps use threaded animations would help nearly everyone wanting thread support.
Check trunk. The current Terrain system already uses externally registered handlers for background tasks. It does use the standard WorkQueue and threads, and we still have our own structures for Requests / Responses, but that's because we need them if we're going to do request any background processing ourselves. It's still perfectly possible to externalise the handling of those requests/responses and the starting of threads, but we still need a hub to hang our own tasks off. It would be pointless for me to engineer a situation where I needed to create another external thread system in an Ogre sample, but we will always allow it (and we do already - WorkQueue is entirely, trivially replaceable with your own implementation).
_tommo_ wrote:I'm proposing that Ogre should only PASSIVELY provide threading:
it should provide itself and more importantly its internal tasks in a way that is easy to pick up and integrate in my own centralised thread scheduler, but without imposing any particular threading scheme on the user;
i don't push request to Ogre's workQueues to run, rather i pull Ogre's requests and run them as i want, where i want, on the thread i want... as long that i respect their dependencies.
Of course, You can build any default work scheme on top of this, but at the same time (should i have too much time in my hands

) i could create a work scheme where ogre does nothing without passing its tasks to my scheduler.
This would be fine except that lots of users don't want it this way. I'm quite happy to implement my own threading outside of Ogre, as are you, and as is steven. But you shouldn't assume for a second that's a universal opinion - in fact far more users just want to say 'load things in the background please' and forget about it. By implementing your option exclusively, I'd be saying to people "You can have parallelism in Ogre, but only if you know how to implement the guts of the process in your own app". That's not acceptable to me, or to a large number of our users.
Instead, I want to allow both modes. By default, the 'easy' mode when Ogre drives the WorkQueue for you will be used. I know you don't like that, but large numbers of other people do. For those that want to drive the tasks externally, you'll be able to do that too - either by plugging in your own WorkQueue implementation which simply delegates to your own task queues, or by using the existing queue but telling OGRE not to start any threads, so the items on it remain unprocessed until your threads deal with them.
At the end of the day, there needs to be a default threading implementation because our samples already use it, and in future pushing more tasks across cores is going to be more rather than less common, even in the core. I definitely want to keep the user in control of that if they want to be, using their own thread pools and prioritisation strategies, but that doesn't for a second mean that there shouldn't be a default that more modest users can just use out of the box, and that we can use in our samples. The two are not mutually exclusive in the slightest.
sparkprime wrote:I have a background loading thread that loads the closest resources to the camera first. One submits a request to the background loader from the rendering thread. Since objects move, their distance needs to be recalculated and updated in the background loader. With a message-based system you'd have to send update messages and process them. All I did is have a volatile float field that I updated every frame. Trivially simple and the fastest solution possible. I think you just have to mix/match things as appropriate rather than defining a single model for all.
And if you choose, you could still share memory across your threads if you know that special case is safe. What I'm proposing here is that the general rule is that no general API call is threadsafe anymore, and that we thread loading (and other tasks like terrain calculations, as I do already) without requiring that. At a stroke this removes all of the locking that was mostly unnecessary but had to be there
just in case because the API was generally threadsafe in the resource areas. You can of course still special case some things if you know they're safe, but that's very different to assuming general thread safety. When I've used this approach in external applications I've special-cased shared memory sometimes too, and that's fine, but because the core was never threadsafe I didn't incur all the safety checks that reduced my performance unnecessarily.
So to sum up, I'm proposing this new mode because:
- It's more efficient when threading is enabled
- It's easier to explain to users
- It's easier to extend to more tasks without propagating an unlimited number of locks throughout the API
- It's easier for users to integrate into their own thread systems; because it's all going through one place (WorkQueue) and the base principles are easier to explain
- It's easier to maintain / less error prone (only if we get rid of the other modes)