Пример #1
0
        /// <summary>
        /// Gets an instance from the pool.
        /// </summary>
        /// <returns>An instance of <typeparamref name="T"/>.</returns>
        public T Get(Thread thread)
        {
            DequeEnumerator de;

            if (instances.TryGet(thread, out de))
            {
                T instance = default(T);
                if (de.Deque.LocalPop(ref instance))
                {
                    return(instance);
                }
                else
                {
                    de.Enumerator.Reset();
                    while (de.Enumerator.MoveNext())
                    {
                        if (de.Enumerator.Current.Value.Deque.TrySteal(ref instance))
                        {
                            return(instance);
                        }
                    }
                }
            }

            return(new T());
        }
Пример #2
0
        public void Wait(int id)
        {
            WaitOrExecute(id);

            Exception[] e;
            if (exceptions.TryGet(id, out e))
            {
                throw new TaskException(e);
            }
        }
Пример #3
0
        public bool DoWork(int expectedID)
        {
            using (executionLock.AcquireExclusiveUsing())
            {
                if (expectedID < runCount)
                {
                    return(true);
                }
                if (work == null)
                {
                    return(false);
                }
                if (executing == work.Options.MaximumThreads)
                {
                    return(false);
                }
                executing++;
            }

            // associate the current task with this thread, so that Task.CurrentTask gives the correct result
            Stack <Task> tasks = null;

            if (!runningTasks.TryGet(Thread.CurrentThread, out tasks))
            {
                tasks = new Stack <Task>();
                runningTasks.Add(Thread.CurrentThread, tasks);
            }
            tasks.Push(new Task(this));

            // execute the task
            try
            {
                // Set work data to running if able
                if (WorkData != null)
                {
                    WorkData.WorkState = ParallelTasks.WorkData.WorkStateEnum.RUNNING;
                }

                work.DoWork(WorkData);

                // Set work data to succeeded if able and not failed
                if (WorkData != null && WorkData.WorkState == ParallelTasks.WorkData.WorkStateEnum.RUNNING)
                {
                    WorkData.WorkState = ParallelTasks.WorkData.WorkStateEnum.SUCCEEDED;
                }
            }
            catch (Exception e)
            {
                if (exceptionBuffer == null)
                {
                    var newExceptions = new List <Exception>();
                    Interlocked.CompareExchange(ref exceptionBuffer, newExceptions, null);
                }

                lock (exceptionBuffer)
                    exceptionBuffer.Add(e);
            }

            if (tasks != null)
            {
                tasks.Pop();
            }

            using (executionLock.AcquireExclusiveUsing())
            {
                executing--;
                if (executing == 0)
                {
                    if (exceptionBuffer != null)
                    {
#if UNSHARPER
                        //workaround for volatile int to const int& casting problem in c++.
                        int val = runCount;
                        exceptions.Add(val, exceptionBuffer.ToArray());
#else
                        exceptions.Add(runCount, exceptionBuffer.ToArray());
#endif
                    }
                    // wait for all children to complete
                    foreach (var child in children)
                    {
                        child.Wait();
                    }

                    runCount++;

                    // open the reset event, so tasks waiting on this one can continue
                    resetEvent.Set();

                    // wait for waiting tasks to all exit
                    while (waitCount > 0)
                    {
                        ;
                    }

                    if (Callback == null && DataCallback == null)
                    {
                        Requeue();
                    }
                    else
                    {
                        // if we have a callback, then queue for execution
                        CompletionCallbacks.Add(this);
                    }

                    return(true);
                }
                return(false);
            }
        }
Пример #4
0
        public bool DoWork(int expectedID)
        {
            using (executionLock.AcquireExclusiveUsing())
            {
                if (expectedID < runCount)
                {
                    return(true);
                }
                if (work == null)
                {
                    return(false);
                }
                if (executing == work.Options.MaximumThreads)
                {
                    return(false);
                }
                executing++;
            }

            // associate the current task with this thread, so that Task.CurrentTask gives the correct result
            Stack <Task> tasks = null;

            if (!runningTasks.TryGet(Thread.CurrentThread, out tasks))
            {
                tasks = new Stack <Task>();
                runningTasks.Add(Thread.CurrentThread, tasks);
            }
            tasks.Push(new Task(this));

            // execute the task
            try { work.DoWork(); }
            catch (Exception e)
            {
                if (exceptionBuffer == null)
                {
                    var newExceptions = new List <Exception>();
                    Interlocked.CompareExchange(ref exceptionBuffer, newExceptions, null);
                }

                lock (exceptionBuffer)
                    exceptionBuffer.Add(e);
            }

            if (tasks != null)
            {
                tasks.Pop();
            }

            using (executionLock.AcquireExclusiveUsing())
            {
                executing--;
                if (executing == 0)
                {
                    if (exceptionBuffer != null)
                    {
                        exceptions.Add(runCount, exceptionBuffer.ToArray());
                    }

                    // wait for all children to complete
                    foreach (var child in children)
                    {
                        child.Wait();
                    }

                    runCount++;

                    // open the reset event, so tasks waiting on this one can continue
                    resetEvent.Set();

                    // wait for waiting tasks to all exit
                    while (waitCount > 0)
                    {
                        ;
                    }

                    if (Callback == null)
                    {
                        Requeue();
                    }
                    else
                    {
                        // if we have a callback, then queue for execution
                        lock (AwaitingCallbacks)
                            AwaitingCallbacks.Add(this);
                    }

                    return(true);
                }
                return(false);
            }
        }