Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Untangled - Sneak Peek at Project Loom

Arnaud Bos
October 05, 2019

Untangled - Sneak Peek at Project Loom

Given at Voxxed Days Ticino 2019
Video: http://bit.ly/untangled-lugano-2019-video
Abstract:
Concurrent programming borrows a lot of terms from weaving and twists our minds with intertwined concepts: fibers, threads, lightweight-threads, green threads, loom… Maybe you’ve heard about coroutines? Don’t worry, everything is linked.

During this talk, we’ll get weaving, show code samples and talk about project Loom, whose goal is to bring “lightweight concurrency“ mechanisms to the JVM, along with APIs to embroider the story.

We will talk about project Loom’s inception and recent prototypes. You will also see its mesh goes far beyond “simple“ primitives to revolutionize the JVM.

Arnaud Bos

October 05, 2019
Tweet

More Decks by Arnaud Bos

Other Decks in Technology

Transcript

  1. private Connection.Available getConnection(long eta, long wait, String token) { for(;;)

    { if (eta > MAX_ETA_MS) { throw new EtaExceededException(); } if (wait > 0) { Thread.sleep(wait); } println("Retrying download after " + wait + "ms wait."); Connection c = coordinator.requestConnection(token); if (c instanceof Connection.Available) { return (Connection.Available) c; } Connection.Unavailable unavail = (Connection.Unavailable) c; eta = unavail.getEta(); wait = unavail.getWait(); token = unavail.getToken(); } }
  2. public static InputStream blockingRequest(String url, String headers) throws IOException {

    URL uri = new URL(url); SocketAddress serverAddress = new InetSocketAddress(uri.getHost(), uri.getP SocketChannel channel = SocketChannel.open(serverAddress); ByteBuffer buffer = ByteBuffer.wrap((headers + "Host: " + uri.getHost() + " do { channel.write(buffer); } while(buffer.hasRemaining()); return channel.socket().getInputStream(); }
  3. private void getThingy(int i, CompletionHandler<Void> handler) { println("Start getThingy."); getConnection(new

    CompletionHandler<>() { @Override public void completed(Connection.Available conn) { println("Got token, " + conn.getToken()); CompletableFuture<Void> downloadFut = new CompletableFuture<>(); gateway.downloadThingy(new RequestHandler() { private int total = 0; private boolean pulsing = false; private boolean cancelled = false; @Override public void received(byte[] data) { int read = data.length; println(i + " :: Thingy received " + read); if (!pulsing) { Runnable pulse = new PulseRunnable(i, downloadFut, con boundedPulseExecutor.schedule(pulse, 2_000L, TimeUnit. pulsing = true; } // ... to be continued
  4. public static void asyncNonBlockingRequest(ExecutorService executor, String url, String headers, RequestHandler

    handler) { executor.submit(() -> { try { println("Starting request to " + url); URL uri = new URL(url); SocketAddress serverAddress = new InetSocketAddress(uri.getHost(), 80); AsynchronousSocketChannel channel = AsynchronousSocketChannel.open(group); channel.connect(serverAddress, null, new CompletionHandler<Void>() { @Override public void completed(Void result, Void attachment) { ByteBuffer headersBuffer = ByteBuffer.wrap((headers + "Host: " + uri.ge ByteBuffer responseBuffer = ByteBuffer.allocate(1024); channel.write(headersBuffer, headersBuffer, new CompletionHandler<>() { @Override public void completed(Integer written, ByteBuffer attachment) { if (attachment.hasRemaining()) { channel.write(attachment, attachment, this); } else { channel.read(responseBuffer, responseBuffer, new Completion @Override public void completed(Integer read, ByteBuffer attachment) { // More // this // way // ==>
  5. private Mono<Connection.Available> getConnection(long eta, long wait, String token) { AtomicLong

    etaRef = new AtomicLong(eta); AtomicLong waitRef = new AtomicLong(wait); AtomicReference<String> tokenRef = new AtomicReference<>(token); return Mono.defer(() -> { if (etaRef.get() > MAX_ETA_MS) { return Mono.error(new EtaExceededException()); } return Mono.delay(Duration.ofMillis(waitRef.get())) .flatMap(i -> coordinator.requestConnection(tokenRef.get())); }).flatMap(c -> { if (c instanceof Connection.Available) { return Mono.just((Connection.Available) c); } else { Connection.Unavailable unavail = (Connection.Unavailable) c; etaRef.set(unavail.getEta()); waitRef.set(unavail.getWait()); tokenRef.set(unavail.getToken()); return Mono.empty(); } }).repeatWhenEmpty(Repeat .onlyIf(ctx -> true) .doOnRepeat(ctx -> println(waitRef.get() + ", " + etaRef.get() + ", " + tokenRef.get()))); }
  6. private Mono<Connection.Available> getConnection(long eta, long wait, String token) { AtomicLong

    etaRef = new AtomicLong(eta); AtomicLong waitRef = new AtomicLong(wait); AtomicReference<String> tokenRef = new AtomicReference<>(token); return Mono.defer(() -> { if (etaRef.get() > MAX_ETA_MS) { return Mono.error(new EtaExceededException()); } return Mono.delay(Duration.ofMillis(waitRef.get())) .flatMap(i -> coordinator.requestConnection(tokenRef.get())); }).flatMap(c -> { if (c instanceof Connection.Available) { return Mono.just((Connection.Available) c); } else { Connection.Unavailable unavail = (Connection.Unavailable) c; etaRef.set(unavail.getEta()); waitRef.set(unavail.getWait()); tokenRef.set(unavail.getToken()); return Mono.empty(); } }).repeatWhenEmpty(Repeat .onlyIf(ctx -> true) .doOnRepeat(ctx -> println(waitRef.get() + ", " + etaRef.get() + ", " + tokenRef.get()))); }
  7. class StateMachineIterator implements Iterator<String> { private int state; private int

    i; public String next() { switch(state) { case 0: state=1; return "A"; case 1: state=2; i=0; return "B"; case 2: if(i == 3) state = 3; return "C" + (i++); case 3: state=4; return "D"; case 4: state=5; return "E"; default: throw new NoSuchElementException(); } } public boolean hasNext() { return state < 5; } public void remove() { throw new UnsupportedOperationException("Not supported"); } }
  8. class StateMachineIterator implements Iterator<String> { private int state; private int

    i; public String next() { switch(state) { case 0: state=1; return "A"; case 1: state=2; i=0; return "B"; case 2: if(i == 3) state = 3; return "C" + (i++); case 3: state=4; return "D"; case 4: state=5; return "E"; default: throw new NoSuchElementException(); } } public boolean hasNext() { return state < 5; } public void remove() { throw new UnsupportedOperationException("Not supported"); } }
  9. class StateMachineIterator implements Iterator<String> { private int state; private int

    i; public String next() { switch(state) { case 0: state=1; return "A"; case 1: state=2; i=0; return "B"; case 2: if(i == 3) state = 3; return "C" + (i++); case 3: state=4; return "D"; case 4: state=5; return "E"; default: throw new NoSuchElementException(); } } public boolean hasNext() { return state < 5; } public void remove() { throw new UnsupportedOperationException("Not supported"); } }
  10. class StateMachineIterator implements Iterator<String> { private int state; private int

    i; public String next() { switch(state) { case 0: state=1; return "A"; case 1: state=2; i=0; return "B"; case 2: if(i == 3) state = 3; return "C" + (i++); case 3: state=4; return "D"; case 4: state=5; return "E"; default: throw new NoSuchElementException(); } } public boolean hasNext() { return state < 5; } public void remove() { throw new UnsupportedOperationException("Not supported"); } }
  11. private Connection.Available getConnection(long eta, long wait, String token) { for(;;)

    { if (eta > MAX_ETA_MS) { throw new EtaExceededException(); } if (wait > 0) { Thread.sleep(wait); } println("Retrying download after " + wait + "ms wait."); Connection c = coordinator.requestConnection(token); if (c instanceof Connection.Available) { return (Connection.Available) c; } Connection.Unavailable unavail = (Connection.Unavailable) c; eta = unavail.getEta(); wait = unavail.getWait(); token = unavail.getToken(); } }
  12. Connection.Available conn = getConnection(); Runnable pulse = makePulse(conn); Fiber<Object> f

    = null; try (InputStream content = gateway.downloadThingy()) { f = FiberScope.background().schedule(pulse); ignoreContent(content); } catch (IOException e) { err("Download failed."); throw e; } finally { if (f!=null) { f.cancel(); } }
  13. Papers and Webpages Flynn, Michael J. - Some Computer Organizations

    and Their Effectiveness Haynes, Christopher T. - Logic Continuations Wand, Mitchell - Continuation-based Multiprocessing Loitsch, Florian - Exceptional Continuations in JavaScript Long, James - What's In A Continuation Reynolds, John C. - The Discoveries of Continuations Clinger, Hartheimer, Ost - Implementation Strategies for Continuations Haynes, Friedman, Wand - Obtaining Coroutines with Continuations Pressler, Ron - Why Continuations are Coming to Java Repos https://github.com/forax/loom-fiber/ https://bitbucket.org/arnaudbos/untangled/