runOnce

Remi Forax forax at univ-mlv.fr
Tue Sep 25 03:44:14 PDT 2012


On 09/25/2012 12:16 PM, Aleksey Shipilev wrote:
> This is bulky and requires Runners class per each call site.
>
> BTW, realized this seem to be pure jsr292 topic, not jsr335.

Like every people that have used the jsr292 in Java, you clearly see
the lack of support of invokedynamic by javac.
Here, your asking the compiler to emit an invokedynamic instead of an 
invokestatic when calling
Runner.runOnce(), I've already discuss with Brian and John Rose to have 
a way to do exactly that
in a type safe way but it will not be scheduled for java 8.

So it's not a pure jsr292 issue, it's an issue between the jsr292 and 
java the language,
we have to finish the integration of jsr292 in Java the language.

BTW, here is the current way to write what you want in Java with jsr 292
and as you say, you still need a static somewhere.

   private static final MethodHandle mh = Runner.runOnce(() -> 
System.out.println("Boo!"));

   public static void bar() {
     try {
       mh.invokeExact();
     } catch(Throwable t){}
   }

   static class Runner {
     public static void nop() {}

     static MethodHandle runOnce(Runnable runnable) {
       MethodType type = MethodType.methodType(void.class);
       MutableCallSite cs = new MutableCallSite(type);
       Lookup lookup = MethodHandles.lookup();
       MethodHandle mh, mh2;
       try {
         mh = lookup.bind(runnable, "run", type);
         mh2 = lookup.bind(cs, "setTarget", 
MethodType.methodType(void.class, MethodHandle.class))
             .bindTo(lookup.findStatic(Runner.class, "nop", type));
       } catch (NoSuchMethodException | IllegalAccessException e) {
         throw new AssertionError(e);
       }
       cs.setTarget(MethodHandles.filterReturnValue(mh, mh2));
       return cs.dynamicInvoker();
     }
   }


>
> -Aleksey.

Rémi

>
> On 09/25/2012 01:59 PM, Remi Forax wrote:
>> without any javac translation:
>>
>>    static class Runners {static { System.out.println("Boo!"); } static
>> void runOnce() {}}
>>    public static void foo() {
>>      Runners.runOnce();
>>    }
>>
>> Rémi
>>
>> On 09/25/2012 11:45 AM, Aleksey Shipilev wrote:
>>> Hi guys,
>>>
>>> This thread [1] makes me thinking if we want to introduce something like
>>> runOnce() to record per-callsite invocation information. I.e. instead of
>>> messing with maps and flags to guard this behavior, one can possibly do:
>>>
>>>     Runners.runOnce(() -> System.out.println("Boo!"));
>>>
>>> ...where runOnce will be desugared by Javac into indy call in which
>>> bootstrap method calls the callee, and then emits the constant callsite
>>> holding the result. This will effectively record the "invoked" property
>>> into callsite, so that this code:
>>>
>>>     Runners.runOnce(() -> System.out.println("foo"));
>>>     Runners.runOnce(() -> System.out.println("bar"));
>>>
>>> would yield:
>>>     foo
>>>     bar
>>>
>>> It might be yet another convenient way to make singletons (err...
>>> thread-safe identity caches), like:
>>>
>>>    public T getInstance() { return Runners.runOnce(() -> new T()); }
>>>
>>> Was something like this considered before?
>>>
>>> -Aleksey.
>>>
>>> [1]
>>> http://mail.openjdk.java.net/pipermail/lambda-dev/2012-September/006015.html
>>>



More information about the lambda-libs-spec-observers mailing list