Page 1 of 1

Threading on Windows RT

Posted: Sat Feb 23, 2013 4:02 am
by Syntax
Hey, I have read some of the other posts here about the threading issue on Windows RT but was wondering if anyone has been able to get it to work. I am using Monogame to port my game to Windows 8 but cannot move forward until I can get around these threading errors. Norbo, I saw on your blog that this wasn't a big priority for you due to your current project, but do you have an idea of when you will be able to work on it? I am under a time constraint and have never had to do multithreaded programming so I am well over my head trying to fix it myself. Thanks.

Re: Threading on Windows RT

Posted: Sat Feb 23, 2013 5:13 am
by Norbo
The changes shouldn't be all that significant. A quick way is to just delete IThreadManager's AddThread, RemoveThread, EnqueueTask, and WaitForTaskCompletion, get rid of the existing thread manager implementations, and create a new IThreadManager implementation which just passes the ForLoops directly through to the framework's own thread pool.

The resulting thread manager would end up looking something like this:

Code: Select all

    public class ThreadManagerPassThrough : IThreadManager
    {

        public int ThreadCount
        {
            get; set;
        }


        public void ForLoop(int startIndex, int endIndex, Action<int> loopBody)
        {
            Parallel.For(startIndex, endIndex, loopBody);
        }

    }
For best performance, ThreadCount should be set to however many threads your for loop is capable of running (e.g. 4 on a Q6600, 8 on a 3770K). The ThreadCount is used to determine if a multithreaded dispatch should occur and, in a few places, also determines how to pre-split workloads.

Then, you'll have to deal with some issues in the SpinLock I believe. If I'm not mistaken, Thread.SpinWait will need to be replaced by a usage of System.Threading.SpinWait. There are some subtleties to deal with there- the existing loop includes yielding logic, but the System.Threading.SpinWait has its own yielding logic. It would require deeper investigation to determine the optimal configuration, but for mere correctness, something like this should work:

Code: Select all

        /// <summary>
        /// Enters the critical section.  A thread cannot attempt to enter the spinlock if it already owns the spinlock.
        /// </summary>
        public void Enter()
        {
            var spinWait = new SpinWait();
            while (Interlocked.CompareExchange(ref owner, 0, -1) != -1)
            {
                spinWait.SpinOnce();
            }
            //It's my lock now!
        }
The above assumes, of course, that the System.Threading.SpinWait structure is available. I can't guarantee that given some of the goofy API changes with WinRT... I would have suggested just using the SpinLock from .NET, but the last time I suggested that, it was reported that SpinLock is not available on WinRT. (I don't yet fully believe this, but I haven't bothered to verify.)
but do you have an idea of when you will be able to work on it?
Chances are, I'm going to procrastinate as long as possible ;)

What would help in the interim is a list of all the necessary changes. So, once you give the above changes a try, let me know if it works or if there are further (or fewer!) changes needed. At the very least, this will allow me to narrow down suggestions in the future. That'll also speed me up once I get around to making modifications.