Search in sources :

Example 6 with Strand

use of co.paralleluniverse.strands.Strand in project quasar by puniverse.

the class ActorTest method testSpawnWithStrandFactory.

@Test
public void testSpawnWithStrandFactory() throws Exception {
    final AtomicBoolean run = new AtomicBoolean(false);
    Actor<Message, Integer> actor = new BasicActor<Message, Integer>(mailboxConfig) {

        @Override
        protected Integer doRun() throws SuspendExecution, InterruptedException {
            run.set(true);
            return 3;
        }
    };
    ActorRef a = actor.spawn(new StrandFactoryBuilder().setFiber(null).setNameFormat("my-fiber-%d").build());
    Strand s = LocalActor.getStrand(a);
    assertTrue(s.isFiber());
    assertThat(s.getName(), equalTo("my-fiber-0"));
    assertThat((Integer) LocalActor.get(a), equalTo(3));
    assertThat(run.get(), is(true));
    run.set(false);
    actor = new BasicActor<Message, Integer>(mailboxConfig) {

        @Override
        protected Integer doRun() throws SuspendExecution, InterruptedException {
            run.set(true);
            return 3;
        }
    };
    a = actor.spawn(new StrandFactoryBuilder().setThread(false).setNameFormat("my-thread-%d").build());
    s = LocalActor.getStrand(a);
    assertTrue(!s.isFiber());
    assertThat(s.getName(), equalTo("my-thread-0"));
    LocalActor.join(a);
    assertThat(run.get(), is(true));
    run.set(false);
    Actor<Message, Integer> actor2 = new BasicActor<Message, Integer>("coolactor", mailboxConfig) {

        @Override
        protected Integer doRun() throws SuspendExecution, InterruptedException {
            run.set(true);
            return 3;
        }
    };
    a = actor2.spawn(new StrandFactoryBuilder().setFiber(null).setNameFormat("my-fiber-%d").build());
    s = LocalActor.getStrand(a);
    assertTrue(s.isFiber());
    assertThat(s.getName(), equalTo("coolactor"));
    assertThat((Integer) LocalActor.get(a), equalTo(3));
    assertThat(run.get(), is(true));
    run.set(false);
    actor2 = new BasicActor<Message, Integer>("coolactor", mailboxConfig) {

        @Override
        protected Integer doRun() throws SuspendExecution, InterruptedException {
            run.set(true);
            return 3;
        }
    };
    a = actor2.spawn(new StrandFactoryBuilder().setThread(false).setNameFormat("my-thread-%d").build());
    s = LocalActor.getStrand(a);
    assertTrue(!s.isFiber());
    assertThat(s.getName(), equalTo("coolactor"));
    LocalActor.join(a);
    assertThat(run.get(), is(true));
    run.set(false);
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) SuspendExecution(co.paralleluniverse.fibers.SuspendExecution) StrandFactoryBuilder(co.paralleluniverse.strands.StrandFactoryBuilder) Strand(co.paralleluniverse.strands.Strand) Test(org.junit.Test)

Example 7 with Strand

use of co.paralleluniverse.strands.Strand in project quasar by puniverse.

the class StampedLock method acquireWrite.

/**
     * See above for explanation.
     *
     * @param interruptible true if should check interrupts and if so
     * return INTERRUPTED
     * @param deadline if nonzero, the System.nanoTime value to timeout
     * at (and return zero)
     * @return next state, or INTERRUPTED
     */
private long acquireWrite(boolean interruptible, long deadline) throws SuspendExecution {
    WNode node = null, p;
    for (int spins = -1; ; ) {
        // spin while enqueuing
        long s, ns;
        if (((s = state) & ABITS) == 0L) {
            if (U.compareAndSwapLong(this, STATE, s, ns = s + WBIT))
                return ns;
        } else if (spins > 0) {
            if (ThreadLocalRandom.current().nextInt() >= 0)
                --spins;
        } else if ((p = wtail) == null) {
            // initialize queue
            WNode h = new WNode(WMODE, null);
            if (U.compareAndSwapObject(this, WHEAD, null, h))
                wtail = h;
        } else if (spins < 0)
            spins = (p == whead) ? SPINS : 0;
        else if (node == null)
            node = new WNode(WMODE, p);
        else if (node.prev != p)
            node.prev = p;
        else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
            p.next = node;
            break;
        }
    }
    for (int spins = SPINS; ; ) {
        WNode np, pp;
        int ps;
        long s, ns;
        Strand w;
        while ((np = node.prev) != p && np != null) // stale
        (p = np).next = node;
        if (whead == p) {
            for (int k = spins; ; ) {
                // spin at head
                if (((s = state) & ABITS) == 0L) {
                    if (U.compareAndSwapLong(this, STATE, s, ns = s + WBIT)) {
                        whead = node;
                        node.prev = null;
                        return ns;
                    }
                } else if (ThreadLocalRandom.current().nextInt() >= 0 && --k <= 0)
                    break;
            }
            if (spins < MAX_HEAD_SPINS)
                spins <<= 1;
        }
        if ((ps = p.status) == 0)
            U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
        else if (ps == CANCELLED) {
            if ((pp = p.prev) != null) {
                node.prev = pp;
                pp.next = node;
            }
        } else {
            // 0 argument to park means no timeout
            long time;
            if (deadline == 0L)
                time = 0L;
            else if ((time = deadline - System.nanoTime()) <= 0L)
                return cancelWaiter(node, node, false);
            node.strand = Strand.currentStrand();
            if (// recheck
            node.prev == p && p.status == WAITING && (p != whead || (state & ABITS) != 0L))
                park(time);
            node.strand = null;
            if (interruptible && Strand.interrupted())
                return cancelWaiter(node, node, true);
        }
    }
}
Also used : Strand(co.paralleluniverse.strands.Strand)

Example 8 with Strand

use of co.paralleluniverse.strands.Strand in project quasar by puniverse.

the class StampedLock method cancelWaiter.

/**
     * If node non-null, forces cancel status and unsplices it from
     * queue if possible and wakes up any cowaiters (of the node, or
     * group, as applicable), and in any case helps release current
     * first waiter if lock is free. (Calling with null arguments
     * serves as a conditional form of release, which is not currently
     * needed but may be needed under possible future cancellation
     * policies). This is a variant of cancellation methods in
     * AbstractQueuedSynchronizer (see its detailed explanation in AQS
     * internal documentation).
     *
     * @param node if nonnull, the waiter
     * @param group either node or the group node is cowaiting with
     * @param interrupted if already interrupted
     * @return INTERRUPTED if interrupted or Strand.interrupted, else zero
     */
private long cancelWaiter(WNode node, WNode group, boolean interrupted) {
    if (node != null && group != null) {
        Strand w;
        node.status = CANCELLED;
        node.strand = null;
        // unsplice cancelled nodes from group
        for (WNode p = group, q; (q = p.cowait) != null; ) {
            if (q.status == CANCELLED)
                U.compareAndSwapObject(p, WNEXT, q, q.next);
            else
                p = q;
        }
        if (group == node) {
            // detach and wake up uncancelled co-waiters
            WNode r;
            while ((r = node.cowait) != null) {
                if (U.compareAndSwapObject(node, WCOWAIT, r, r.cowait) && (w = r.strand) != null) {
                    r.strand = null;
                    w.unpark();
                }
            }
            for (WNode pred = node.prev; pred != null; ) {
                // unsplice
                // find valid successor
                WNode succ, pp;
                while ((succ = node.next) == null || succ.status == CANCELLED) {
                    // find successor the slow way
                    WNode q = null;
                    for (WNode t = wtail; t != null && t != node; t = t.prev) if (t.status != CANCELLED)
                        // don't link if succ cancelled
                        q = t;
                    if (// ensure accurate successor
                    succ == q || U.compareAndSwapObject(node, WNEXT, succ, succ = q)) {
                        if (succ == null && node == wtail)
                            U.compareAndSwapObject(this, WTAIL, node, pred);
                        break;
                    }
                }
                if (// unsplice pred link
                pred.next == node)
                    U.compareAndSwapObject(pred, WNEXT, node, succ);
                if (succ != null && (w = succ.strand) != null) {
                    succ.strand = null;
                    // wake up succ to observe new pred
                    w.unpark();
                }
                if (pred.status != CANCELLED || (pp = pred.prev) == null)
                    break;
                // repeat if new pred wrong/cancelled
                node.prev = pp;
                U.compareAndSwapObject(pp, WNEXT, pred, succ);
                pred = pp;
            }
        }
    }
    // Possibly release first waiter
    WNode h;
    while ((h = whead) != null) {
        long s;
        // similar to release() but check eligibility
        WNode q;
        if ((q = h.next) == null || q.status == CANCELLED) {
            for (WNode t = wtail; t != null && t != h; t = t.prev) if (t.status <= 0)
                q = t;
        }
        if (h == whead) {
            if (q != null && h.status == 0 && // waiter is eligible
            ((s = state) & ABITS) != WBIT && (s == 0L || q.mode == RMODE))
                release(h);
            break;
        }
    }
    return (interrupted || Strand.interrupted()) ? INTERRUPTED : 0L;
}
Also used : Strand(co.paralleluniverse.strands.Strand)

Example 9 with Strand

use of co.paralleluniverse.strands.Strand in project quasar by puniverse.

the class TransferChannel method awaitMatch.

/**
     * Spins/yields/blocks until node s is matched or caller gives up.
     *
     * @param s     the waiting node
     * @param pred  the predecessor of s, or s itself if it has no
     *              predecessor, or null if unknown (the null case does not occur
     *              in any current calls but may in possible future extensions)
     * @param e     the comparison value for checking match
     * @param timed if true, wait only until timeout elapses
     * @param nanos timeout in nanosecs, used only if timed is true
     * @return matched item, or e if unmatched on interrupt or timeout
     */
private Message awaitMatch(Node s, Node pred, Message e, boolean timed, long nanos) throws SuspendExecution {
    long lastTime = timed ? System.nanoTime() : 0L;
    Strand w = Strand.currentStrand();
    // no spins in fiber; otherwise, initialized after first item and cancel checks
    int spins = (w.isFiber() ? 0 : -1);
    // bound if needed
    ThreadLocalRandom randomYields = null;
    if (spins == 0)
        requestUnpark(s, w);
    for (; ; ) {
        Object item = s.item;
        if (item == CHANNEL_CLOSED)
            setReceiveClosed();
        if (item != e) {
            // matched
            // assert item != s;
            // avoid garbage
            s.forgetContents();
            return this.<Message>cast(item);
        }
        if ((w.isInterrupted() || (timed && nanos <= 0)) && s.casItem(e, s)) {
            // cancel
            unsplice(pred, s);
            return e;
        }
        if (spins < 0) {
            // establish spins at/near front
            if ((spins = spinsFor(pred, s.isData)) > 0)
                randomYields = ThreadLocalRandom.current();
        } else if (spins > 0) {
            // spin
            --spins;
            if (randomYields.nextInt(CHAINED_SPINS) == 0)
                // occasionally yield
                Strand.yield();
        } else if (s.waiter == null) {
            // request unpark then recheck
            requestUnpark(s, w);
        } else if (timed) {
            long now = System.nanoTime();
            if ((nanos -= now - lastTime) > 0)
                Strand.parkNanos(this, nanos);
            lastTime = now;
        } else {
            Strand.park(this);
        }
    }
}
Also used : ThreadLocalRandom(java.util.concurrent.ThreadLocalRandom) Strand(co.paralleluniverse.strands.Strand)

Example 10 with Strand

use of co.paralleluniverse.strands.Strand in project quasar by puniverse.

the class AbstractQueuedLongSynchronizer method fullGetFirstQueuedStrand.

/**
     * Version of getFirstQueuedStrand called when fastpath fails
     */
private Strand fullGetFirstQueuedStrand() {
    /*
         * The first node is normally head.next. Try to get its
         * strand field, ensuring consistent reads: If strand
         * field is nulled out or s.prev is no longer head, then
         * some other strand(s) concurrently performed setHead in
         * between some of our reads. We try this twice before
         * resorting to traversal.
         */
    Node h, s;
    Strand st;
    if (((h = head) != null && (s = h.next) != null && s.prev == head && (st = s.strand) != null) || ((h = head) != null && (s = h.next) != null && s.prev == head && (st = s.strand) != null))
        return st;
    /*
         * Head's next field might not have been set yet, or may have
         * been unset after setHead. So we must check to see if tail
         * is actually first node. If not, we continue on, safely
         * traversing from tail back to head to find first,
         * guaranteeing termination.
         */
    Node t = tail;
    Strand firstStrand = null;
    while (t != null && t != head) {
        Strand tt = t.strand;
        if (tt != null)
            firstStrand = tt;
        t = t.prev;
    }
    return firstStrand;
}
Also used : Strand(co.paralleluniverse.strands.Strand)

Aggregations

Strand (co.paralleluniverse.strands.Strand)27 Fiber (co.paralleluniverse.fibers.Fiber)8 SuspendableRunnable (co.paralleluniverse.strands.SuspendableRunnable)4 SuspendExecution (co.paralleluniverse.fibers.SuspendExecution)3 Test (org.junit.Test)2 Actor (co.paralleluniverse.actors.Actor)1 ActorRef (co.paralleluniverse.actors.ActorRef)1 LocalActor (co.paralleluniverse.actors.LocalActor)1 FlightRecorderMessage (co.paralleluniverse.common.monitoring.FlightRecorderMessage)1 Pair (co.paralleluniverse.common.util.Pair)1 StrandFactoryBuilder (co.paralleluniverse.strands.StrandFactoryBuilder)1 Channel (co.paralleluniverse.strands.channels.Channel)1 ReceivePort (co.paralleluniverse.strands.channels.ReceivePort)1 SendPort (co.paralleluniverse.strands.channels.SendPort)1 ExecutionException (java.util.concurrent.ExecutionException)1 ThreadLocalRandom (java.util.concurrent.ThreadLocalRandom)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 AtomicReference (java.util.concurrent.atomic.AtomicReference)1 Publisher (org.reactivestreams.Publisher)1