示例#1
0
        /// <summary> Process tasks until w is done.
        /// Equivalent to <code>while(!w.isDone()) taskYield(); </code>
        ///
        /// </summary>

        protected internal void  taskJoin(FJTask w)
        {
            while (!w.Done)
            {
                FJTask task = pop();
                if (task != null)
                {
                    if (!task.Done)
                    {
                        if (CollectStats)
                        {
                            ++runs;
                        }
                        task.Run();
                        task.SetDone();
                        if (task == w)
                        {
                            return;                              // fast exit if we just ran w
                        }
                    }
                }
                else
                {
                    scan(w);
                }
            }
        }
示例#2
0
        /* ------------  composite operations ------------------- */


        /// <summary> Main runloop
        ///
        /// </summary>

        private void DoStart()
        {
            try
            {
                while (!Interrupted)
                {
                    FJTask task = pop();
                    if (task != null)
                    {
                        if (!task.Done)
                        {
                            // inline FJTask.invoke
                            if (CollectStats)
                            {
                                ++runs;
                            }
                            task.Run();
                            task.SetDone();
                        }
                    }
                    else
                    {
                        scanWhileIdling();
                    }
                }
            }
            finally
            {
                group_.Inactive = this;
            }
        }
示例#3
0
        /// <summary> Immediately execute task t by calling its run method. Has no
        /// effect if t has already been run or has been cancelled.
        /// It is equivalent to  calling t.run except that it
        /// deals with completion status, so should always be used
        /// instead of directly calling run.
        /// The method can be useful
        /// when a computation has been packaged as a FJTask, but you just need to
        /// directly execute its body from within some other task.
        ///
        /// </summary>

        public static void  Invoke(FJTask t)
        {
            if (!t.Done)
            {
                t.Run();
                t.SetDone();
            }
        }
示例#4
0
        /// <summary> A specialized expansion of
        /// <code> w.fork(); invoke(v); w.join(); </code>
        ///
        /// </summary>


        protected internal void  coInvoke(FJTask w, FJTask v)
        {
            // inline  push

            int t = top;

            if (t < (base_Renamed & (deq.Length - 1)) + deq.Length)
            {
                deq[t & (deq.Length - 1)].Put(w);
                top = t + 1;

                // inline  invoke

                if (!v.Done)
                {
                    if (CollectStats)
                    {
                        ++runs;
                    }
                    v.Run();
                    v.SetDone();
                }

                // inline  taskJoin

                while (!w.Done)
                {
                    FJTask task = pop();
                    if (task != null)
                    {
                        if (!task.Done)
                        {
                            if (CollectStats)
                            {
                                ++runs;
                            }
                            task.Run();
                            task.SetDone();
                            if (task == w)
                            {
                                return;                                  // fast exit if we just ran w
                            }
                        }
                    }
                    else
                    {
                        scan(w);
                    }
                }
            }
            // handle non-inlinable cases
            else
            {
                slowCoInvoke(w, v);
            }
        }
示例#5
0
        /// <summary> Execute a task in this thread. Generally called when current task
        /// cannot otherwise continue.
        ///
        /// </summary>


        protected internal void  taskYield()
        {
            FJTask task = pop();

            if (task != null)
            {
                if (!task.Done)
                {
                    if (CollectStats)
                    {
                        ++runs;
                    }
                    task.Run();
                    task.SetDone();
                }
            }
            else
            {
                scan(null);
            }
        }
示例#6
0
 /// <summary> Immediately execute task t by calling its run method. Has no
 /// effect if t has already been run or has been cancelled.
 /// It is equivalent to  calling t.run except that it
 /// deals with completion status, so should always be used
 /// instead of directly calling run.
 /// The method can be useful
 /// when a computation has been packaged as a FJTask, but you just need to 
 /// directly execute its body from within some other task.
 /// 
 /// </summary>
 public static void Invoke(FJTask t)
 {
     if (!t.Done)
     {
         t.Run();
         t.SetDone();
     }
 }
示例#7
0
        /// <summary> A specialized expansion of
        /// <code> w.fork(); invoke(v); w.join(); </code>
        /// 
        /// </summary>
        protected internal void coInvoke(FJTask w, FJTask v)
        {
            // inline  push

            int t = top;
            if (t < (base_Renamed & (deq.Length - 1)) + deq.Length)
            {

                deq[t & (deq.Length - 1)].Put(w);
                top = t + 1;

                // inline  invoke

                if (!v.Done)
                {
                    if (CollectStats)
                        ++runs;
                    v.Run();
                    v.SetDone();
                }

                // inline  taskJoin

                while (!w.Done)
                {
                    FJTask task = pop();
                    if (task != null)
                    {
                        if (!task.Done)
                        {
                            if (CollectStats)
                                ++runs;
                            task.Run();
                            task.SetDone();
                            if (task == w)
                                return ; // fast exit if we just ran w
                        }
                    }
                    else
                        scan(w);
                }
            }
            // handle non-inlinable cases
            else
                slowCoInvoke(w, v);
        }
示例#8
0
        /// <summary> Same as scan, but called when current thread is idling.
        /// It repeatedly scans other threads for tasks,
        /// sleeping while none are available.
        /// <p>
        /// This differs from scan mainly in that
        /// since there is no reason to return to recheck any
        /// condition, we iterate until a task is found, backing
        /// off via sleeps if necessary.
        /// </p>
        ///
        /// </summary>

        protected internal virtual void  scanWhileIdling()
        {
            FJTask task = null;

            bool lowered = false;
            long iters   = 0;

            FJTaskRunner[] ts  = group_.Array;
            int            idx = victimRNG.Next(ts.Length);

            do
            {
                for (int i = 0; i < ts.Length; ++i)
                {
                    FJTaskRunner t = ts[idx];
                    if (++idx >= ts.Length)
                    {
                        idx = 0;                         // circularly traverse
                    }
                    if (t != null && t != this)
                    {
                        if (CollectStats)
                        {
                            ++scans;
                        }

                        task = t.take();
                        if (task != null)
                        {
                            if (CollectStats)
                            {
                                ++steals;
                            }
                            if (lowered)
                            {
                                Priority = (ThreadPriority)runPriority_;
                            }
                            group_.SetActive(this);
                            break;
                        }
                    }
                }

                if (task == null)
                {
                    if (Interrupted)
                    {
                        return;
                    }

                    if (CollectStats)
                    {
                        ++scans;
                    }
                    task = group_.PollEntryQueue(this);

                    if (task != null)
                    {
                        if (CollectStats)
                        {
                            ++steals;
                        }
                        if (lowered)
                        {
                            Priority = (ThreadPriority)runPriority_;
                        }
                        group_.SetActive(this);
                    }
                    else
                    {
                        ++iters;
                        //  Check here for yield vs sleep to avoid entering group synch lock
                        if (iters >= FJTaskRunnerGroup.ScansPerSleep)
                        {
                            group_.CheckActive(this, iters);
                            if (Interrupted)
                            {
                                return;
                            }
                        }
                        else if (!lowered)
                        {
                            lowered  = true;
                            Priority = (ThreadPriority)scanPriority_;
                        }
                        else
                        {
                            Thread.Sleep(0);
                        }
                    }
                }
            }while (task == null);


            if (!task.Done)
            {
                if (CollectStats)
                {
                    ++runs;
                }
                task.Run();
                task.SetDone();
            }
        }
示例#9
0
        /* ------------ Scheduling  ------------------- */


        /// <summary> Do all but the pop() part of yield or join, by
        /// traversing all DEQs in our group looking for a task to
        /// steal. If none, it checks the entry queue.
        /// <p>
        /// Since there are no good, portable alternatives,
        /// we rely here on a mixture of Thread.yield and priorities
        /// to reduce wasted spinning, even though these are
        /// not well defined. We are hoping here that the JVM
        /// does something sensible.
        /// </p>
        /// </summary>
        /// <param name="waitingFor">if non-null, the current task being joined
        ///
        /// </param>

        protected internal virtual void  scan(FJTask waitingFor)
        {
            FJTask task = null;

            // to delay lowering priority until first failure to steal
            bool lowered = false;

            /*
             * Circularly traverse from a random start index.
             *
             * This differs slightly from cilk version that uses a random index
             * for each attempted steal.
             * Exhaustive scanning might impede analytic tractablity of
             * the scheduling policy, but makes it much easier to deal with
             * startup and shutdown.
             */

            FJTaskRunner[] ts  = group_.Array;
            int            idx = victimRNG.Next(ts.Length);

            for (int i = 0; i < ts.Length; ++i)
            {
                FJTaskRunner t = ts[idx];
                if (++idx >= ts.Length)
                {
                    idx = 0;                     // circularly traverse
                }
                if (t != null && t != this)
                {
                    if (waitingFor != null && waitingFor.Done)
                    {
                        break;
                    }
                    else
                    {
                        if (CollectStats)
                        {
                            ++scans;
                        }
                        task = t.take();
                        if (task != null)
                        {
                            if (CollectStats)
                            {
                                ++steals;
                            }
                            break;
                        }
                        else
                        {
                            if (Interrupted)
                            {
                                break;
                            }
                            else if (!lowered)
                            {
                                // if this is first fail, lower priority
                                lowered  = true;
                                Priority = (ThreadPriority)scanPriority_;
                            }
                            else
                            {
                                // otherwise we are at low priority; just yield
                                Thread.Sleep(0);
                            }
                        }
                    }
                }
            }

            if (task == null)
            {
                if (CollectStats)
                {
                    ++scans;
                }
                task = group_.PollEntryQueue(this);
                if (CollectStats)
                {
                    if (task != null)
                    {
                        ++steals;
                    }
                }
            }

            if (lowered)
            {
                Priority = (ThreadPriority)runPriority_;
            }

            if (task != null && !task.Done)
            {
                if (CollectStats)
                {
                    ++runs;
                }
                task.Run();
                task.SetDone();
            }
        }
示例#10
0
        /// <summary> Array-based version of coInvoke
        ///
        /// </summary>

        protected internal void  coInvoke(FJTask[] tasks)
        {
            int nforks = tasks.Length - 1;

            // inline bulk push of all but one task

            int t = top;

            if (nforks >= 0 && t + nforks < (base_Renamed & (deq.Length - 1)) + deq.Length)
            {
                for (int i = 0; i < nforks; ++i)
                {
                    deq[t++ & (deq.Length - 1)].Put(tasks[i]);
                    top = t;
                }

                // inline invoke of one task
                FJTask v = tasks[nforks];
                if (!v.Done)
                {
                    if (CollectStats)
                    {
                        ++runs;
                    }
                    v.Run();
                    v.SetDone();
                }

                // inline  taskJoins

                for (int i = 0; i < nforks; ++i)
                {
                    FJTask w = tasks[i];
                    while (!w.Done)
                    {
                        FJTask task = pop();
                        if (task != null)
                        {
                            if (!task.Done)
                            {
                                if (CollectStats)
                                {
                                    ++runs;
                                }
                                task.Run();
                                task.SetDone();
                            }
                        }
                        else
                        {
                            scan(w);
                        }
                    }
                }
            }
            // handle non-inlinable cases
            else
            {
                slowCoInvoke(tasks);
            }
        }