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

Project Loom : la concurrence au bout du fil

Arnaud Bos
September 13, 2019

Project Loom : la concurrence au bout du fil

Given at JUG Summer Camp 2019
Video: http://bit.ly/loom-jug-summer-camp-2019-video
Abstract:
Le domaine de la programmation concurrente utilise le champ lexical de la filature et nous met les nerfs en pelote avec des concepts qui s’entrelacent : fibers, threads, lightweight-threads, green threads, loom…

Peut-être avez vous également entendu parler de coroutines ? Rassurez-vous, tout est lié.

En 15 minutes je vous donnerai un aperçu de ce que le projet Loom ambitionne d’apporter à la JVM et de quelle façon vous pouvez déjà en profiter, sans trop tirer sur la corde, avec Quasar.

Arnaud Bos

September 13, 2019
Tweet

More Decks by Arnaud Bos

Other Decks in Technology

Transcript

  1. #JSC2019 @arnaud_bos 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. #JSC2019 @arnaud_bos 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
  3. #JSC2019 @arnaud_bos 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 !// !!==>
  4. #JSC2019 @arnaud_bos 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()))); }
  5. #JSC2019 @arnaud_bos 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. #JSC2019 @arnaud_bos 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"); } }
  7. #JSC2019 @arnaud_bos 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. #JSC2019 @arnaud_bos 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. #JSC2019 @arnaud_bos 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. #JSC2019 @arnaud_bos 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(); } }