puniverse / quasar

Fibers, Channels and Actors for the JVM
http://docs.paralleluniverse.co/quasar/
Other
4.56k stars 575 forks source link

Groovy support for FiberAsync #329

Open devent opened 4 years ago

devent commented 4 years ago

Hi. I was trying Quasar and was wondering why the examples are not working if I use Groovy and FiberAsync. Here is a slightly modified example code taken from FiberAsyncTest.java but complied with Groovy in QuasarFiberAsyncTest.groovy. The behavior should be identical with the Java compiled version. But it either throws a TimeoutException or never returns from a fiber.join().

Quasar: 0.8.0 Groovy: 2.5.7 Usage: -ea -javaagent:${QUASAR_CORE_AGENT_JAR}

/*
 * Quasar: lightweight threads and actors for the JVM.
 * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.
 *
 * This program and the accompanying materials are dual-licensed under
 * either the terms of the Eclipse Public License v1.0 as published by
 * the Eclipse Foundation
 *
 *   or (per the licensee's choosing)
 *
 * under the terms of the GNU Lesser General Public License version 3.0
 * as published by the Free Software Foundation.
 */
package com.anrisoftware.dwarfhustle.graph.janus.internal;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.junit.jupiter.api.Test;

import co.paralleluniverse.fibers.Fiber;
import co.paralleluniverse.fibers.FiberAsync;
import co.paralleluniverse.fibers.FiberForkJoinScheduler;
import co.paralleluniverse.fibers.SuspendExecution;
import co.paralleluniverse.strands.SuspendableRunnable;

/**
 *
 * @author pron
 */
public class QuasarFiberAsyncTest {

    interface MyCallback {
        void call(String str);

        void fail(RuntimeException e);
    }

    interface Service {
        void registerCallback(MyCallback callback);
    }

    static abstract class MyFiberAsync extends FiberAsync<String, RuntimeException> implements MyCallback {
        private final Fiber fiber;

        public MyFiberAsync() {
            this.fiber = Fiber.currentFiber();
        }

        @Override
        public void call(String str) {
            super.asyncCompleted(str);
        }

        @Override
        public void fail(RuntimeException e) {
            super.asyncFailed(e);
        }
    }

    static String callService(final Service service) throws SuspendExecution, InterruptedException {
        println "callService"
        return new MyFiberAsync() {
                    @Override
                    protected void requestAsync() {
                        println "requestAsync"
                        service.registerCallback(this);
                    }
                }.run();
    }

    @Test
    public void testSyncCallback() throws Exception {
        FiberForkJoinScheduler scheduler = new FiberForkJoinScheduler("test", 4, null, false);
        final Service syncService = new Service() {
                    @Override
                    public void registerCallback(MyCallback callback) {
                        callback.call("sync result!");
                    }
                };
        final Fiber fiber = new Fiber(scheduler) {
                    @Override
                    protected Object run() throws SuspendExecution, InterruptedException {
                        String res = callService(syncService);
                        System.out.println(res);
                        return res;
                    }
                }.start();

        // never returns
        // fiber.join();
        // throws TimeoutException
        fiber.join(1, TimeUnit.SECONDS);
    }
}

Console output:

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.codehaus.groovy.vmplugin.v7.Java7$1 (file:/home/erwin/.m2/repository/org/codehaus/groovy/groovy/2.5.7/groovy-2.5.7.jar) to constructor java.lang.invoke.MethodHandles$Lookup(java.lang.Class,int)
WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.vmplugin.v7.Java7$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
QUASAR WARNING: Assertions enabled. This may harm performance.
callService
requestAsync
callService

As you can see, callService is two times in the output. In the Java version the output is:

JRE Oracle Corporation/12.0.1 is not supported, advanced source lookup disabled.
QUASAR WARNING: Assertions enabled. This may harm performance.
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access using Lookup on co.paralleluniverse.concurrent.util.ThreadAccess (file:/home/erwin/.m2/repository/co/paralleluniverse/quasar-core/0.8.0/quasar-core-0.8.0.jar) to class java.lang.Thread
WARNING: Please consider reporting this to the maintainers of co.paralleluniverse.concurrent.util.ThreadAccess
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
callService
requestAsync
sync result!
devent commented 4 years ago

Update: if I use Groovy groovy.transform.CompileStatic annotation then FiberAsync works like the Java version. It's an Ok workaround, but would be nice if Quasar could support dynamic Groovy.

See http://docs.groovy-lang.org/latest/html/gapi/groovy/transform/CompileStatic.html