Esempio n. 1
0
        /// <summary>
        /// Awaits completion or aborts on interrupt or timeout.
        /// </summary>
        /// <param name="timed"> true if use timed waits </param>
        /// <param name="nanos"> time to wait, if timed </param>
        /// <returns> state upon completion </returns>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private int awaitDone(boolean timed, long nanos) throws InterruptedException
        private int AwaitDone(bool timed, long nanos)
        {
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final long deadline = timed ? System.nanoTime() + nanos : 0L;
            long     deadline = timed ? System.nanoTime() + nanos : 0L;
            WaitNode q        = null;
            bool     queued   = false;

            for (;;)
            {
                if (Thread.Interrupted())
                {
                    RemoveWaiter(q);
                    throw new InterruptedException();
                }

                int s = State;
                if (s > COMPLETING)
                {
                    if (q != null)
                    {
                        q.Thread = null;
                    }
                    return(s);
                }
                else if (s == COMPLETING)                 // cannot time out yet
                {
                    Thread.@yield();
                }
                else if (q == null)
                {
                    q = new WaitNode();
                }
                else if (!queued)
                {
                    queued = UNSAFE.compareAndSwapObject(this, WaitersOffset, q.Next = Waiters, q);
                }
                else if (timed)
                {
                    nanos = deadline - System.nanoTime();
                    if (nanos <= 0L)
                    {
                        RemoveWaiter(q);
                        return(State);
                    }
                    LockSupport.ParkNanos(this, nanos);
                }
                else
                {
                    LockSupport.Park(this);
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Ensures that any interrupt from a possible cancel(true) is only
        /// delivered to a task while in run or runAndReset.
        /// </summary>
        private void HandlePossibleCancellationInterrupt(int s)
        {
            // It is possible for our interrupter to stall before getting a
            // chance to interrupt us.  Let's spin-wait patiently.
            if (s == INTERRUPTING)
            {
                while (State == INTERRUPTING)
                {
                    Thread.@yield();                     // wait out pending interrupt
                }
            }

            // assert state == INTERRUPTED;

            // We want to clear any interrupt we may have received from
            // cancel(true).  However, it is permissible to use interrupts
            // as an independent mechanism for a task to communicate with
            // its caller, and there is no way to clear only the
            // cancellation interrupt.
            //
            // Thread.interrupted();
        }
Esempio n. 3
0
        /// <summary>
        /// Exchange function used until arenas enabled. See above for explanation.
        /// </summary>
        /// <param name="item"> the item to exchange </param>
        /// <param name="timed"> true if the wait is timed </param>
        /// <param name="ns"> if timed, the maximum wait time, else 0L </param>
        /// <returns> the other thread's item; or null if either the arena
        /// was enabled or the thread was interrupted before completion; or
        /// TIMED_OUT if timed and timed out </returns>
        private Object SlotExchange(Object item, bool timed, long ns)
        {
            Node   p = Participant.Get();
            Thread t = Thread.CurrentThread;

            if (t.Interrupted)             // preserve interrupt status so caller can recheck
            {
                return(null);
            }

            for (Node q;;)
            {
                if ((q = Slot) != null)
                {
                    if (U.compareAndSwapObject(this, SLOT,q,null))
                    {
                        Object v = q.item;
                        q.match = item;
                        Thread w = q.parked;
                        if (w != null)
                        {
                            U.unpark(w);
                        }
                        return(v);
                    }
                    // create arena on contention, but continue until slot null
                    if (NCPU > 1 && Bound == 0 && U.compareAndSwapInt(this,BOUND,0,SEQ))
                    {
                        Arena = new Node[(FULL + 2) << ASHIFT];
                    }
                }
                else if (Arena != null)
                {
                    return(null);                    // caller must reroute to arenaExchange
                }
                else
                {
                    p.Item = item;
                    if (U.compareAndSwapObject(this,SLOT,null,p))
                    {
                        break;
                    }
                    p.Item = null;
                }
            }

            // await release
            int    h     = p.Hash;
            long   end   = timed ? System.nanoTime() + ns : 0L;
            int    spins = (NCPU > 1) ? SPINS : 1;
            Object v;

            while ((v = p.Match) == null)
            {
                if (spins > 0)
                {
                    h ^= h << 1;
                    h ^= (int)((uint)h >> 3);
                    h ^= h << 10;
                    if (h == 0)
                    {
                        h = SPINS | (int)t.Id;
                    }
                    else if (h < 0 && (--spins & (((int)((uint)SPINS >> 1)) - 1)) == 0)
                    {
                        Thread.@yield();
                    }
                }
                else if (Slot != p)
                {
                    spins = SPINS;
                }
                else if (!t.Interrupted && Arena == null && (!timed || (ns = end - System.nanoTime()) > 0L))
                {
                    U.putObject(t,BLOCKER,this);
                    p.Parked = t;
                    if (Slot == p)
                    {
                        U.park(false,ns);
                    }
                    p.Parked = null;
                    U.putObject(t,BLOCKER,null);
                }
                else if (U.compareAndSwapObject(this,SLOT,p,null))
                {
                    v = timed && ns <= 0L && !t.Interrupted ? TIMED_OUT : null;
                    break;
                }
            }
            U.putOrderedObject(p,MATCH,null);
            p.Item = null;
            p.Hash = h;
            return(v);
        }
Esempio n. 4
0
        /// <summary>
        /// Exchange function when arenas enabled. See above for explanation.
        /// </summary>
        /// <param name="item"> the (non-null) item to exchange </param>
        /// <param name="timed"> true if the wait is timed </param>
        /// <param name="ns"> if timed, the maximum wait time, else 0L </param>
        /// <returns> the other thread's item; or null if interrupted; or
        /// TIMED_OUT if timed and timed out </returns>
        private Object ArenaExchange(Object item, bool timed, long ns)
        {
            Node[] a = Arena;
            Node   p = Participant.Get();

            for (int i = p.Index;;)          // access slot at i
            {
                int  b, m, c;                // j is raw array offset
                long j;
                Node q = (Node)U.getObjectVolatile(a, j = (i << ASHIFT) + ABASE);
                if (q != null && U.compareAndSwapObject(a, j, q, null))
                {
                    Object v = q.Item;                     // release
                    q.Match = item;
                    Thread w = q.Parked;
                    if (w != null)
                    {
                        U.unpark(w);
                    }
                    return(v);
                }
                else if (i <= (m = (b = Bound) & MMASK) && q == null)
                {
                    p.Item = item;                     // offer
                    if (U.compareAndSwapObject(a, j, null, p))
                    {
                        long   end = (timed && m == 0) ? System.nanoTime() + ns : 0L;
                        Thread t   = Thread.CurrentThread;                       // wait
                        for (int h = p.Hash, spins = SPINS;;)
                        {
                            Object v = p.Match;
                            if (v != null)
                            {
                                U.putOrderedObject(p, MATCH, null);
                                p.Item = null;                                 // clear for next use
                                p.Hash = h;
                                return(v);
                            }
                            else if (spins > 0)
                            {
                                h ^= h << 1;                                 // xorshift
                                h ^= (int)((uint)h >> 3);
                                h ^= h << 10;
                                if (h == 0)                                 // initialize hash
                                {
                                    h = SPINS | (int)t.Id;
                                }
                                else if (h < 0 && (--spins & (((int)((uint)SPINS >> 1)) - 1)) == 0) // approx 50% true
                                {
                                    Thread.@yield();                                                // two yields per wait
                                }
                            }
                            else if (U.getObjectVolatile(a, j) != p)
                            {
                                spins = SPINS;                                 // releaser hasn't set match yet
                            }
                            else if (!t.Interrupted && m == 0 && (!timed || (ns = end - System.nanoTime()) > 0L))
                            {
                                U.putObject(t, BLOCKER, this);                // emulate LockSupport
                                p.Parked = t;                                 // minimize window
                                if (U.getObjectVolatile(a, j) == p)
                                {
                                    U.park(false, ns);
                                }
                                p.Parked = null;
                                U.putObject(t, BLOCKER, null);
                            }
                            else if (U.getObjectVolatile(a, j) == p && U.compareAndSwapObject(a, j, p, null))
                            {
                                if (m != 0)                                 // try to shrink
                                {
                                    U.compareAndSwapInt(this, BOUND, b, b + SEQ - 1);
                                }
                                p.Item = null;
                                p.Hash = h;
                                i      = p.Index = (int)((uint)p.Index >> 1);                            // descend
                                if (Thread.Interrupted())
                                {
                                    return(null);
                                }
                                if (timed && m == 0 && ns <= 0L)
                                {
                                    return(TIMED_OUT);
                                }
                                break;                                 // expired; restart
                            }
                        }
                    }
                    else
                    {
                        p.Item = null;                         // clear offer
                    }
                }
                else
                {
                    if (p.Bound != b)                     // stale; reset
                    {
                        p.Bound    = b;
                        p.Collides = 0;
                        i          = (i != m || m == 0) ? m : m - 1;
                    }
                    else if ((c = p.Collides) < m || m == FULL || !U.compareAndSwapInt(this, BOUND, b, b + SEQ + 1))
                    {
                        p.Collides = c + 1;
                        i          = (i == 0) ? m : i - 1;                // cyclically traverse
                    }
                    else
                    {
                        i = m + 1;                         // grow
                    }
                    p.Index = i;
                }
            }
        }