use of co.paralleluniverse.strands.Strand in project quasar by puniverse.
the class Pipeline method parallelTransfer.
private void parallelTransfer() throws SuspendExecution, InterruptedException {
// 1) Fire workers
for (int i = 0; i < parallelism; i++) {
strandFactory.newStrand(SuspendableUtils.runnableToCallable(new SuspendableRunnable() {
@Override
public void run() throws SuspendExecution, InterruptedException {
// Get first job
Pair<S, Channel<Channel<T>>> job = jobs.receive();
while (job != null) {
// Build result channel
final Channel<T> res = resultChannelBuilder.run();
// Process
transformer.call(job.getFirst(), res);
final Channel<Channel<T>> resWrapper = job.getSecond();
// Send result asynchronously
strandFactory.newStrand(SuspendableUtils.runnableToCallable(new SuspendableRunnable() {
@Override
public void run() throws SuspendExecution, InterruptedException {
resWrapper.send(res);
}
})).start();
// Get next job
job = jobs.receive();
}
// No more jobs, close results channel and quit worker
results.close();
}
})).start();
}
// 2) Send jobs asynchronously
strandFactory.newStrand(SuspendableUtils.runnableToCallable(new SuspendableRunnable() {
@Override
public void run() throws SuspendExecution, InterruptedException {
// Get first input
S s = from.receive();
while (s != null) {
final Channel<Channel<T>> resultWrapper = Channels.newChannel(1, Channels.OverflowPolicy.BLOCK, true, true);
jobs.send(new Pair<>(s, resultWrapper));
results.send(resultWrapper);
// Get next input
s = from.receive();
}
// No more inputs, close jobs channel and quit
jobs.close();
}
})).start();
// 3) Collect and transfer results asynchronously
try {
final Strand collector = strandFactory.newStrand(SuspendableUtils.runnableToCallable(new SuspendableRunnable() {
@Override
public void run() throws SuspendExecution, InterruptedException {
// Get first result
Channel<Channel<T>> resWrapper = results.receive();
while (resWrapper != null) {
// Get wrapper
Channel<T> res = resWrapper.receive();
// Get first actual result
T out = res.receive();
while (out != null) {
// Send to output channel
to.send(out);
// Increment counter
transferred.incrementAndGet();
// Get next result
out = res.receive();
}
resWrapper = results.receive();
}
// No more results, quit
}
})).start();
// TODO solve nasty instrumentation problems on Strand.join()
if (collector.isFiber()) {
Fiber f = (Fiber) collector.getUnderlying();
f.join();
} else
collector.join();
} catch (ExecutionException ee) {
throw new AssertionError(ee);
}
}
use of co.paralleluniverse.strands.Strand in project quasar by puniverse.
the class AbstractQueuedSynchronizer 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;
}
Aggregations